diff options
| -rw-r--r-- | maildrop/Makefile.am | 4 | ||||
| -rw-r--r-- | maildrop/mailbot.c | 173 | ||||
| -rw-r--r-- | maildrop/mailbot.sgml | 153 | ||||
| -rw-r--r-- | rfc2045/rfc2045reply.c | 93 | 
4 files changed, 347 insertions, 76 deletions
| diff --git a/maildrop/Makefile.am b/maildrop/Makefile.am index d37d054..0367891 100644 --- a/maildrop/Makefile.am +++ b/maildrop/Makefile.am @@ -57,10 +57,10 @@ reformail_DEPENDENCIES = $(reformail_LDADD)  noinst_PROGRAMS=maildrop reformail mailbot  mailbot_SOURCES=mailbot.c -mailbot_DEPENDENCIES=../rfc2045/librfc2045.la \ +mailbot_DEPENDENCIES=../rfc2045/librfc2045.la ../maildir/libmaildir.la \  	../rfc822/librfc822.la ../liblock/liblock.la \  	../numlib/libnumlib.la $(DBLIB) -mailbot_LDADD=../rfc2045/librfc2045.la \ +mailbot_LDADD=../rfc2045/librfc2045.la ../maildir/libmaildir.la \  	../rfc822/librfc822.la ../liblock/liblock.la \  	../numlib/libnumlib.la $(DBLIB) -lunicode  mailbot_LDFLAGS = -static diff --git a/maildrop/mailbot.c b/maildrop/mailbot.c index 5fbb860..2ae29d3 100644 --- a/maildrop/mailbot.c +++ b/maildrop/mailbot.c @@ -1,5 +1,5 @@  /* -** Copyright 2001-2010 Double Precision, Inc. +** Copyright 2001-2014 Double Precision, Inc.  ** See COPYING for distribution information.  */ @@ -7,6 +7,7 @@  #include "dbobj.h"  #include "liblock/config.h"  #include "liblock/liblock.h" +#include "maildir/maildirmisc.h"  #include <unicode.h>  #include "numlib/numlib.h"  #include <string.h> @@ -27,6 +28,9 @@  #include "rfc2045/rfc2045.h"  #include "rfc2045/rfc2045charset.h"  #include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h>  #include "mywait.h"  #include <signal.h>  #if HAVE_SYSEXITS_H @@ -74,7 +78,7 @@ static void usage()  		"    -e                 - Prefer replies to Errors-To: or Return-Path: instead\n"  		"                         of From:\n"  		"    -T type            - \"type\": reply, replyall, replydsn, replyfeedback,\n" -		"                         forward, forwardatt\n" +		"                         replydraft, forward, forwardatt\n"  		"    -N                 - Omit contents of the original message from replies\n"  		"    -F \"separator\"     - Set the forwarding separator\n"  		"    -S \"salutation\"    - Set salutation for replies\n" @@ -92,6 +96,8 @@ static void usage()  		"    -n                 - only show the resulting message, do not send it\n"  		"    -a                 - Attach entire message for replydsn, feedback, and\n"  		"                         replyfeedback, instead of only the headers.\n" +		"    -l                 - maildir to read a draft message with the reply\n" +		"                         (required by -T replydraft).\n"  );  	fprintf(stderr, @@ -524,6 +530,137 @@ static void copy_body(void *ptr)  	}  } +static void copy_draft(void *ptr) +{ +	struct mimeautoreply_s *p=(struct mimeautoreply_s *)ptr; +	char buf[BUFSIZ]; +	int copying_this_header=0; +	int continuing=0; + +	while (1) +	{ +		if (!fgets(buf, sizeof(buf), p->contentf)) +			return; + +		if (!continuing) +		{ +			if (*buf == '\n') +				break; + +			if (!isspace(*buf)) +			{ +				/* Copy MIME headers only */ +				copying_this_header= +					strncasecmp(buf, "content-", 8) == 0; +			} +		} + +		continuing=strchr(buf, '\n') == NULL; + +		if (copying_this_header) +			mimeautoreply_write_func(buf, strlen(buf), ptr); +	} + +	do +	{ +		mimeautoreply_write_func(buf, strlen(buf), ptr); +	} while (fgets(buf, sizeof(buf), p->contentf)); +} + +FILE *find_draft(const char *maildirfolder) +{ +	char *draftfile=0; +	struct stat draft_stat; + +	FILE *fp=NULL; +	static const char * const newcur[2]={"new", "cur"}; +	int i; + +	for (i=0; i<2; ++i) +	{ +		char *dirbuf=malloc(strlen(maildirfolder)+10); +		DIR *dirp; +		struct dirent *de; + +		if (!dirbuf) +		{ +			perror("malloc"); +			exit(1); +		} + +		strcat(strcat(strcpy(dirbuf, maildirfolder), "/"), +		       newcur[i]); + +		dirp=opendir(dirbuf); +		if (!dirp) +		{ +			free(dirbuf); +			continue; +		} + +		while ((de=readdir(dirp)) != NULL) +		{ +			const char *filename=de->d_name; +			char *filenamebuf; +			FILE *new_file; +			struct stat new_stat; + +			if (*filename == '.') +				continue; +			if (MAILDIR_DELETED(filename)) +				continue; + +			/* +			** 1st maildir filename component should be creation +			** time_t, take advantage of that. +			*/ + +			if (draftfile && atol(draftfile) > atol(filename)) +				continue; + +			filenamebuf=malloc(strlen(dirbuf)+strlen(filename)+2); +			if (!filenamebuf) +			{ +				perror("malloc"); +				exit(1); +			} +			strcat(strcat(strcpy(filenamebuf, dirbuf), "/"), +			       filename); +			new_file=fopen(filenamebuf, "r"); +			free(filenamebuf); +			if (!new_file) +				continue; + +			if (fstat(fileno(new_file), &new_stat) < 0) +				continue; + +			if (draftfile) +			{ +				if (new_stat.st_mtime < draft_stat.st_mtime) +					continue; + +				if (new_stat.st_mtime == draft_stat.st_mtime +				    && strcmp(filename, draftfile) > 0) +					continue; + +				free(draftfile); +				fclose(fp); +			} + +			if ((draftfile=strdup(filename)) == NULL) +			{ +				perror("strdup"); +				exit(1); +			} +			fp=new_file; +			draft_stat=new_stat; +		} +		free(dirbuf); +		closedir(dirp); +	} +	return fp; +} +  struct fb {  	struct fb *next;  	const char *n; @@ -538,6 +675,7 @@ int main(int argc, char **argv)  	struct mimeautoreply_s replyinfo;  	const char *subj=0;  	const char *txtfile=0, *mimefile=0; +	FILE *draftfile=0;  	const char *mimedsn=0;  	int nosend=0;  	const char *replymode="reply"; @@ -546,6 +684,7 @@ int main(int argc, char **argv)  	int fullmsg=0;  	const char *forwardsep="--- Forwarded message ---";  	const char *replysalut="%F writes:"; +	const char *maildirfolder=0;  	struct rfc2045src *src;  	const char *feedback_type=0; @@ -739,6 +878,11 @@ int main(int argc, char **argv)  				exit(1);  			}  			continue; +		case 'l': +			if (!optarg && argn+1 < argc) +				optarg=argv[++argn]; +			maildirfolder=optarg; +			continue;  		case 'n':  			nosend=1;  			continue; @@ -747,12 +891,22 @@ int main(int argc, char **argv)  		}  	} -	if (!txtfile && !mimefile) -		usage(); - -	if (txtfile && mimefile) -		usage(); +	if (strcmp(replymode, "replydraft") == 0) +	{ +		if (!maildirfolder) +			usage(); +		draftfile=find_draft(maildirfolder); +		if (!draftfile) +			exit(0); +	} +	else +	{ +		if (!txtfile && !mimefile) +			usage(); +		if (txtfile && mimefile) +			usage(); +	}  	tmpfp=tmpfile();  	if (!tmpfp) @@ -915,6 +1069,11 @@ int main(int argc, char **argv)  		}  		replyinfo.info.content_specify=copy_body;  	} +	else if (draftfile) +	{ +		replyinfo.contentf=draftfile; +		replyinfo.info.content_specify=copy_draft; +	}  	if (replyinfo.contentf)  		fcntl(fileno(replyinfo.contentf), F_SETFD, FD_CLOEXEC); diff --git a/maildrop/mailbot.sgml b/maildrop/mailbot.sgml index c9700b2..fdbfe3c 100644 --- a/maildrop/mailbot.sgml +++ b/maildrop/mailbot.sgml @@ -17,14 +17,14 @@    <refsynopsisdiv>      <cmdsynopsis sepchar=" "> -      <command moreinfo="none">mailbot</command> +      <command>mailbot</command>        <arg choice="opt" rep="norepeat">options</arg>        <arg choice="req" rep="norepeat"><replaceable>program</replaceable></arg>        <arg rep="repeat" choice="opt">arg</arg>      </cmdsynopsis>      <informalexample> -      <para>In <filename moreinfo="none">.mailfilter:</filename></para> +      <para>In <filename>.mailfilter:</filename></para>        <programlisting format="linespecific">  if (/^Subject: *info/)  { @@ -39,21 +39,21 @@ if (/^Subject: *info/)      <title>DESCRIPTION</title> -    <para><command moreinfo="none">mailbot</command> reads an E-mail message on standard input +    <para><command>mailbot</command> reads an E-mail message on standard input  and creates an E-mail message replying to the original message's sender.  A -<command moreinfo="none">program</command> is specified as an argument to -<command moreinfo="none">mailbot</command> after all of <command moreinfo="none">mailbot</command> options. -<command moreinfo="none">program</command> is expected to read the +<command>program</command> is specified as an argument to +<command>mailbot</command> after all of <command>mailbot</command> options. +<command>program</command> is expected to read the  created autoreply on its standard input, and mail it. -If <command moreinfo="none">program</command> is not specified, -<command moreinfo="none">mailbot</command> runs '<literal moreinfo="none">sendmail -f ""</literal>'.</para> +If <command>program</command> is not specified, +<command>mailbot</command> runs '<literal>sendmail -f ""</literal>'.</para>      <para> -<command moreinfo="none">mailbot</command> has several options for suppressing duplicate +<command>mailbot</command> has several options for suppressing duplicate  autoresponse messages. -If <command moreinfo="none">mailbot</command> chooses not to send an autoresponse, it quietly -terminates without running <command moreinfo="none">program</command>. +If <command>mailbot</command> chooses not to send an autoresponse, it quietly +terminates without running <command>program</command>.  The autoresponse is optionally  formatted as a MIME delivery status notification.</para> @@ -61,13 +61,16 @@ formatted as a MIME delivery status notification.</para>  The text of the autoresponse is specified by the <option>-t</option> or  the <option>-m</option> argument. Either one is required.  Everything else is optional. +The only exception is the <option>-T replydraft</option> option, which requires +the <option>-l</option> option instead of either <option>-t</option> or +<option>-m</option>.  The default behavior is to send an autoresponse unless the original message -has the "<literal moreinfo="none">Precedence: junk</literal>" or the -"<literal moreinfo="none">Precedence: bulk</literal>" header, or the -"<literal moreinfo="none">Precedence: list</literal>" header, or the -"<literal moreinfo="none">List-ID:</literal>" header, +has the "<literal>Precedence: junk</literal>" or the +"<literal>Precedence: bulk</literal>" header, or the +"<literal>Precedence: list</literal>" header, or the +"<literal>List-ID:</literal>" header,  or if -its MIME content type is "<literal moreinfo="none">multipart/report</literal>" +its MIME content type is "<literal>multipart/report</literal>"  (this is the MIME content type for delivery status notifications).  The <option>-M</option> option formats the  the autoresponse itself as a MIME delivery status notification.</para> @@ -97,9 +100,9 @@ Address the autoresponse to <replaceable>address</replaceable>, which must  be an  <ulink url="http://tools.ietf.org/html/rfc2822">RFC 2822</ulink>  address. -By default <command moreinfo="none">mailbot</command> takes the autoresponse +By default <command>mailbot</command> takes the autoresponse  address from the -<literal moreinfo="none">From:</literal> (or the <literal moreinfo="none">Reply-To:</literal>) header +<literal>From:</literal> (or the <literal>Reply-To:</literal>) header  in the original message.  <option>-f</option>, if present, overrides and explicitly sets the  autoresponse address. @@ -152,7 +155,7 @@ using their original width.</para>  	  <para>  Set the autoresponse's MIME character set to  <replaceable>charset</replaceable>. -Run <command moreinfo="none">mailbot</command> without any arguments to see the +Run <command>mailbot</command> without any arguments to see the  default character set.</para>  	</listitem>        </varlistentry> @@ -160,7 +163,7 @@ default character set.</para>  	<term>-m <replaceable>filename</replaceable></term>  	<listitem>  	  <para> -	    Read a MIME autoresponse from <filename moreinfo="none">filename</filename>. +	    Read a MIME autoresponse from <filename>filename</filename>.  	    This is similar to the <option>-t</option> option,  	    except that <replaceable>filename</replaceable> contains MIME headers,  	    followed by a blank line, and the corresponding @@ -178,7 +181,7 @@ default character set.</para>  	    If the specified file has a <quote>Content-Transfer-Encoding</quote>  	    header it must be either <quote>7bit</quote> or <quote>8bit</quote>,  	    it may not be <quote>quoted-printable</quote>. -	    <command moreinfo="none">mailbot</command> always drops any +	    <command>mailbot</command> always drops any  	    existing <quote>Content-Transfer-Encoding</quote> header and  	    always adds the  	    <quote>Content-Transfer-Encoding: 8bit</quote> header, even with @@ -202,7 +205,7 @@ The lamb was sure to go.</programlisting>  	  <note>  	    <para>  When the <option>-m</option> option is specified -<command moreinfo="none">mailbot</command> ignores the locale's character +<command>mailbot</command> ignores the locale's character  set and formats the autoreply according to the character set read from the  <quote>Content-Type</quote> header.</para>  	  </note> @@ -220,10 +223,10 @@ set and formats the autoreply according to the character set read from the  	    E-mail address that generates the DSN.  	    Note that the <option>-A</option> option should still be used in   	    addition to <option>-M</option> in order to set the -	    <literal moreinfo="none">From:</literal> header on the autoresponse. +	    <literal>From:</literal> header on the autoresponse.  	    <option>-M</option> sets the DSN address only.  	    The <option>-M</option> option automatically sets -	    <option>-T <literal moreinfo="none">replydsn</literal></option> +	    <option>-T <literal>replydsn</literal></option>  	  </para>  	</listitem>        </varlistentry> @@ -274,6 +277,14 @@ set and formats the autoreply according to the character set read from the  	    </listitem>  	    <listitem>  	      <para> +		<quote>replydraft</quote> - like <quote>reply</quote>, with +		the text of the autoresponse coming from a maildir specified +		by the <option>-l</option> option. See <quote>Autoreplies +		  from a maildir folder</quote>, below. +	      </para> +	    </listitem> +	    <listitem> +	      <para>  		<quote>forward</quote> - attach the original message as  		forwarded text.  	      </para> @@ -381,62 +392,62 @@ set and formats the autoreply according to the character set read from the  	  <itemizedlist>  	    <listitem>  	      <para> -		<literal moreinfo="none">%%</literal> - an explicit <literal moreinfo="none">%</literal> +		<literal>%%</literal> - an explicit <literal>%</literal>  		character.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%n</literal> - a newline character. +		<literal>%n</literal> - a newline character.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%C</literal> - the +		<literal>%C</literal> - the  		<quote>X-Newsgroup:</quote> header from the original message.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%N</literal> - the <quote>Newsgroups:</quote> +		<literal>%N</literal> - the <quote>Newsgroups:</quote>  		header from the original message.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%i</literal> - the <quote>Message-ID:</quote> +		<literal>%i</literal> - the <quote>Message-ID:</quote>  		header from the original message.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%f</literal> - the original message's sender's address. +		<literal>%f</literal> - the original message's sender's address.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%F</literal> - the original message's sender's name. +		<literal>%F</literal> - the original message's sender's name.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%S</literal> - the +		<literal>%S</literal> - the  		<quote>Subject:</quote> header from the original message  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%d</literal> - the original message's date, in the +		<literal>%d</literal> - the original message's date, in the  		local timezone.  	      </para>  	    </listitem>  	    <listitem>  	      <para> -		<literal moreinfo="none">%{<replaceable>...</replaceable>}d</literal> -		- use <function moreinfo="none">strftime</function>() to format the original +		<literal>%{<replaceable>...</replaceable>}d</literal> +		- use <function>strftime</function>() to format the original  		message's date. -	        A plain <literal moreinfo="none">%d</literal> is equivalent to -		<literal moreinfo="none">%{%a, %d %b %Y %H:%M:%S %z}d</literal>. +	        A plain <literal>%d</literal> is equivalent to +		<literal>%{%a, %d %b %Y %H:%M:%S %z}d</literal>.  	      </para>  	    </listitem>  	  </itemizedlist> @@ -452,7 +463,7 @@ set and formats the autoreply according to the character set read from the  	<listitem>  	  <para> -	    When generating a <literal moreinfo="none">forward</literal>, use the +	    When generating a <literal>forward</literal>, use the  	    <replaceable>marker</replaceable> to separate the forwarded  	    message from the autoreply text, instead of the default  	    <quote>--- Forwarded message ---</quote> @@ -467,9 +478,9 @@ set and formats the autoreply according to the character set read from the  <replaceable>addrlist</replaceable> is a comma-separated list of  <ulink url="http://tools.ietf.org/html/rfc2822">RFC 2822</ulink>  E-mail addresses. -<command moreinfo="none">mailbot</command> sends an autoresponse only if +<command>mailbot</command> sends an autoresponse only if  the original message has at least one of the specified addresses in any -<literal moreinfo="none">To:</literal> or <literal moreinfo="none">Cc:</literal> header.</para> +<literal>To:</literal> or <literal>Cc:</literal> header.</para>  	</listitem>        </varlistentry>        <varlistentry> @@ -482,7 +493,7 @@ and prevent duplicate autoresponses going to the same address  (suppress autoresponses going back to the same senders, for subsequent  received messages).  The <option>-d</option> option is only available if -<command moreinfo="none">maildrop</command> has GDBM/DB extensions enabled.</para> +<command>maildrop</command> has GDBM/DB extensions enabled.</para>  	</listitem>        </varlistentry>        <varlistentry> @@ -502,7 +513,7 @@ the <option>-D</option> option has elapsed.</para>  	<term>-s "<replaceable>subject</replaceable>"</term>  	<listitem>  	  <para> -Set the <literal moreinfo="none">Subject:</literal> header on the autoresponse to +Set the <literal>Subject:</literal> header on the autoresponse to  <replaceable>subject</replaceable>.</para>  	</listitem>        </varlistentry> @@ -544,9 +555,65 @@ Set the <literal moreinfo="none">Subject:</literal> header on the autoresponse t  	  </para>  	</listitem>        </varlistentry> +      <varlistentry> +	<term>-l <replaceable>maildir</replaceable></term> + +	<listitem> +	  <para> +	    Specifies the maildir for the <quote>-T replydraft</quote> +	    option. See <quote>Autoreplies +	      from a maildir folder</quote>, below. +	  </para> +	</listitem> +      </varlistentry>      </variablelist> -  </refsect1> +    <refsect2> +      <title>Autoreplies from a maildir folder</title> + +      <para>In <filename>.mailfilter:</filename></para> + +      <blockquote> +	<informalexample> +	  <programlisting> +cc "| mailbot -T replydraft -l './Maildir/.Vacation' \ +        -d autoresponsedb \ +        -A 'From: info@domain.com' /usr/bin/sendmail -f ''" +to "./Maildir"</programlisting> +	</informalexample> +      </blockquote> + +      <para> +	The <option>-T replydraft</option> reply format takes the content of +	the autoresponse from the most recent message in a maildir. +	The <option>-l</option> option specifies the maildir. The above +	example takes the message from <literal>$HOME/Maildir/.Drafts</literal> +	which should be a maildir (with the usual <filename>cur</filename>, +	<filename>new</filename>, and <filename>tmp</filename> subdirectories). +	It would typically get created by Courier-IMAP as a folder named +	<quote>Vacation</quote>. +      </para> + +      <para> +	This makes it possible to install autoreplies via an IMAP client by +	creating a folder named <quote>Vacation</quote>, and copying a message +	into it. The contents of the message become the autoresponse. +      </para> + +      <para> +	If the named maildir does not exist, or is empty, +	<command>mailbot</command> does nothing. If the named maildir has +	more than one message, the most recent message gets used. +      </para> + +      <para> +	The above example uses additional <command>mailbot</command> options +	to suppress duplicate autoresponses, and to set the <quote>From:</quote> +	header on the autoresponse. +      </para> +    </refsect2> + +  </refsect1>    <refsect1>      <title>SEE ALSO</title> diff --git a/rfc2045/rfc2045reply.c b/rfc2045/rfc2045reply.c index 3ec0728..28726dc 100644 --- a/rfc2045/rfc2045reply.c +++ b/rfc2045/rfc2045reply.c @@ -908,6 +908,8 @@ static char *mlcheck(struct rfc2045_mkreplyinfo *ri, const char *);  static int replydsn(struct rfc2045_mkreplyinfo *);  static int replyfeedback(struct rfc2045_mkreplyinfo *); +static int replydraft(struct rfc2045_mkreplyinfo *); +static void copyheaders(struct rfc2045_mkreplyinfo *);  static int mkreply(struct rfc2045_mkreplyinfo *ri)  { @@ -1364,6 +1366,15 @@ static int mkreply(struct rfc2045_mkreplyinfo *ri)  		free(subject);  	} +	if (strcmp(ri->replymode, "replydraft") == 0) +	{ +		writes(ri, "\n"); +		if (whowrote) +			free(whowrote); +		whowrote=0; +		return replydraft(ri); +	} +  	writes(ri, "\nMime-Version: 1.0\n");  	boundary=NULL; @@ -1422,6 +1433,7 @@ static int mkreply(struct rfc2045_mkreplyinfo *ri)  		{  			writes(ri, whowrote);  			free(whowrote); +			whowrote=0;  			writes(ri, "\n\n");  		}  		if (SRC_SEEK(ri->src, start_body) == (off_t)-1) @@ -1443,9 +1455,6 @@ static int mkreply(struct rfc2045_mkreplyinfo *ri)  	{  		/* replydsn or replyfeedback */ -		char	*header, *value; -		struct rfc2045headerinfo *hi; -  		writes(ri, "\n--");  		writes(ri, boundary);  		writes(ri, "\nContent-Type: message/"); @@ -1488,27 +1497,7 @@ static int mkreply(struct rfc2045_mkreplyinfo *ri)  		}  		else  		{ -			writes(ri, "\nContent-Type: text/rfc822-headers; charset=\"iso-8859-1\"\n" -			       "Content-Disposition: attachment\n" -			       "Content-Transfer-Encoding: 8bit\n\n" -			       ); - -			hi=rfc2045header_start(ri->src, ri->rfc2045partp); - -			while (hi) -			{ -				if (rfc2045header_get(hi, &header, &value, -						      RFC2045H_NOLC) || !header) -				{ -					rfc2045header_end(hi); -					break; -				} - -				writes(ri, header); -				writes(ri, ": "); -				writes(ri, value); -				writes(ri, "\n"); -			} +			copyheaders(ri);  		}  		writes(ri, "\n--");  		writes(ri, boundary); @@ -1530,6 +1519,62 @@ static void dsn_arrival_date(struct rfc2045_mkreplyinfo *ri)  	writes(ri, "\n");  } +static void copyheaders(struct rfc2045_mkreplyinfo *ri) +{ +	struct rfc2045headerinfo *hi; +	char	*header, *value; + + +	writes(ri, "\nContent-Type: text/rfc822-headers; charset=\"iso-8859-1\"\n" +	       "Content-Disposition: attachment\n" +	       "Content-Transfer-Encoding: 8bit\n\n" +	       ); + +	hi=rfc2045header_start(ri->src, ri->rfc2045partp); + +	while (hi) +	{ +		if (rfc2045header_get(hi, &header, &value, +				      RFC2045H_NOLC) || !header) +		{ +			rfc2045header_end(hi); +			break; +		} + +		writes(ri, header); +		writes(ri, ": "); +		writes(ri, value); +		writes(ri, "\n"); +	} +} + +static int replydraft(struct rfc2045_mkreplyinfo *ri) +{ +	char *boundary=rfc2045_mk_boundary(ri->rfc2045partp, ri->src); +	if (!boundary) +		return (-1); + +	writes(ri, "Content-Type: multipart/mixed; boundary=\""); +	writes(ri, boundary); +	writes(ri, "\"\n\n"); +	writes(ri, RFC2045MIMEMSG); +	writes(ri, "\n--"); +	writes(ri, boundary); +	writes(ri, "\n"); + +	if (ri->content_specify) +		(*ri->content_specify)(ri->voidarg); + +	writes(ri, "\n--"); +	writes(ri, boundary); +	copyheaders(ri); +	writes(ri, "\n--"); +	writes(ri, boundary); +	writes(ri, "--\n"); +	free(boundary); +	return 0; +} +  static int replydsn(struct rfc2045_mkreplyinfo *ri)  {  	dsn_arrival_date(ri); | 
