[Dovecot] Implementation of editheaders in dovecot

Konstantin Lepa konstantin.lepa at gmail.com
Fri Apr 3 17:11:51 EEST 2009


Also, i'd like to know how to cut last '\n' from header stream. If I  
don't remove a last lf symbol, then all my headers'll added to message  
body :-(

On Apr 3, 2009, at 17:37 , Konstantin Lepa wrote:

> I fixed the problem and I created another :-)
>
> I removed header "Subject" and added "X-DSPAM: test value\n\n". Now,  
> problem is message_get_header_size in create_stream_for_msgbody. It  
> returns 0 :-( I don't know how to extract message body properly.  
> Help me to understand usage of struct message_size.
>
> Result:
> . fetch 1 rfc822.header
> * 1 FETCH (RFC822.HEADER {625}
> Return-Path: <pupkin at virtualworld.com>
> Delivered-To: pitman at virtualworld.com
> Received: from localhost.virtualworld.com (localhost [127.0.0.1])
>         by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254
>         for <pitman at virtualworld.com>; Thu,  2 Apr 2009 05:07:51  
> +0400 (MSD)
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> From: pupkin at virtualworld.com
> Reply-to: Konstantin at bsdman.virtualworld.com,
>         Lepa at bsdman.virtualworld.com
> To: pitman at virtualworld.com
> Message-Id: <20090402010751.8AB84254 at bsdman.virtualworld.com>
> Date: Thu,  2 Apr 2009 05:07:51 +0400 (MSD)
>
> )
> . OK Fetch completed.
> . fetch 1 rfc822.text
> * 1 FETCH (RFC822.TEXT {721}
> X-DSPAM: test value
>
> X-DSPAM: test value
>
> Return-Path: <pupkin at virtualworld.com>
> Delivered-To: pitman at virtualworld.com
> Received: from localhost.virtualworld.com (localhost [127.0.0.1])
>         by bsdman.virtualworld.com (Postfix) with ESMTP id 8AB84254
>         for <pitman at virtualworld.com>; Thu,  2 Apr 2009 05:07:51  
> +0400 (MSD)
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Subject: 2009-04-02T05:07:51.464214+1
> From: pupkin at virtualworld.com
> Reply-to: Konstantin at bsdman.virtualworld.com,
>         Lepa at bsdman.virtualworld.com
> To: pitman at virtualworld.com
> Message-Id: <20090402010751.8AB84254 at bsdman.virtualworld.com>
> Date: Thu,  2 Apr 2009 05:07:51 +0400 (MSD)
>
> Message 1
> )
> . OK Fetch completed.
>
> On Apr 3, 2009, at 14:12 , Konstantin Lepa wrote:
>
>> Hello.
>>
>> I wrote the hook function for deliver. I want to add support of  
>> editheaders in the plug-in for dovecot. For this purpose I wrote  
>> the function rarules_get_stream. Remover of headrs works properly,  
>> but adding does not work. I took Timo Sirainen's advice from http://markmail.org/message/skb6arnll5gaopdr 
>>  . Do I use a correct way of creation of a message?
>>
>> I give backtrace and a part of my code.
>>
>> Thanks, Konstantin
>>
>>
>> uname -a:
>> FreeBSD bsdman.virtualworld.com 6.4-RELEASE FreeBSD 6.4-RELEASE #0:  
>> Wed Nov 26 11:43:51 UTC 2008     root at dessler.cse.buffalo.edu:/usr/ 
>> obj/usr/src/sys/GENERIC  i386
>>
>> dovecot --version:
>> 1.1.11
>>
>> build:
>>  $ ./configure --localstatedir=/var --with-statedir=/var/db/dovecot  
>> --without-shadow --enable-debug --with-ioloop=kqueue --disable-ipv6  
>> --with-gssapi --without-vpopmail --without-ldap --without-pgsql -- 
>> with-mysql --without-sqlite --prefix=/usr/local --mandir=/usr/local/ 
>> man --infodir=/usr/local/info/ --build=i386-portbld-freebsd6.4
>>
>> patches: in freebsd ports
>>
>> (gdb) bt
>> #0  0x282f3a01 in memcpy () from /lib/libc.so.6
>> #1  0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at  
>> istream-concat.c:79
>> #2  0x080df784 in i_stream_concat_read (stream=0x814aa00) at  
>> istream-concat.c:136
>> #3  0x080de659 in i_stream_read (stream=0x814aa28) at istream.c:78
>> #4  0x080cd99a in i_stream_header_filter_read (stream=0x814e400) at  
>> istream-header-filter.c:322
>> #5  0x080de659 in i_stream_read (stream=0x814e428) at istream.c:78
>> #6  0x080dff26 in i_stream_crlf_read_common (cstream=0x814ad00) at  
>> istream-crlf.c:41
>> #7  0x080e01b3 in i_stream_crlf_read_lf (stream=0x814ad00) at  
>> istream-crlf.c:103
>> #8  0x080de659 in i_stream_read (stream=0x814ad28) at istream.c:78
>> #9  0x080e2611 in i_stream_tee_read (stream=0x814ae00) at istream- 
>> tee.c:122
>> #10 0x080de659 in i_stream_read (stream=0x814ae28) at istream.c:78
>> #11 0x080deea3 in i_stream_read_data (stream=0x814ae28,  
>> data_r=0xbfbfea88, size_r=0xbfbfea8c, threshold=1) at istream.c:322
>> #12 0x080d1744 in message_parser_read_more (ctx=0x8156468,  
>> block_r=0xbfbfea80, full_r=0xbfbfea27) at message-parser.c:117
>> #13 0x080d20ac in parse_next_body_to_eof (ctx=0x8156468,  
>> block_r=0xbfbfea80) at message-parser.c:411
>> #14 0x080d2ccf in message_parser_parse_next_block (ctx=0x8156468,  
>> block_r=0xbfbfea80) at message-parser.c:765
>> #15 0x080931d9 in index_mail_cache_parse_continue (_mail=0x8150060)  
>> at index-mail.c:1316
>> #16 0x0807838d in mbox_save_continue (_ctx=0x811bb00) at mbox- 
>> save.c:582
>> #17 0x080a05a8 in mailbox_save_continue (ctx=0x811bb00) at mail- 
>> storage.c:740
>> #18 0x0809d9df in mail_storage_copy (t=0x811b980, mail=0x8141860,  
>> flags=0, keywords=0x0, dest_mail=0x0) at mail-copy.c:33
>> #19 0x080a0632 in mailbox_copy (t=0x811b980, mail=0x8141860,  
>> flags=0, keywords=0x0, dest_mail=0x0) at mail-storage.c:763
>> #20 0x0805960d in deliver_save (namespaces=0x8121c68,  
>> storage_r=0xbfbfee14, mailbox=0x811a370 "Draft", mail=0x8141860,
>>     flags=0, keywords=0x0) at deliver.c:234
>> #21 0x2831fe8f in store_in (arg=0x811a370 "Draft", md=0xbfbfed00)  
>> at /home/pitman/work/rarules/src/actions.c:220
>> #22 0x2831f759 in rarules_execute_action  
>> (type=RARULES_ACTION_STORE_IN, arg=0x811a370 "Draft", md=0xbfbfed00)
>>     at /home/pitman/work/rarules/src/actions.c:57
>> #23 0x2831e70d in execute_actions (action=0x811a360, md=0xbfbfed00)  
>> at /home/pitman/work/rarules/src/rarules.c:98
>> #24 0x2831e692 in apply_rules (rule=0x811a320, md=0xbfbfed00) at / 
>> home/pitman/work/rarules/src/rarules.c:80
>> #25 0x2831e56a in rarules_main (namespaces=0x8121c68,  
>> storage_r=0xbfbfee14, mail=0x8141860, db=0x8121000,
>>     destaddr=0xbfbfef62 "pitman at virtualworld.com",  
>> username=0x8113525 "pitman at virtualworld.com", mailbox=0x80f2a19  
>> "INBOX")
>>     at /home/pitman/work/rarules/src/rarules.c:52
>> #26 0x2831da37 in rarules_deliver_mail (namespaces=0x8121c68,  
>> storage_r=0xbfbfee14, mail=0x8141860,
>>     destaddr=0xbfbfef62 "pitman at virtualworld.com",  
>> mailbox=0x80f2a19 "INBOX")
>>     at /home/pitman/work/rarules/src/rarules_plugin.c:126
>> #27 0x0805b69a in main (argc=3, argv=0xbfbfeeac) at deliver.c:1084
>>
>> (gdb) f 1
>> #1  0x080df555 in i_stream_concat_read_next (cstream=0x814aa00) at  
>> istream-concat.c:79
>> 79              memcpy(cstream->istream.w_buffer, data, data_size);
>>
>> (gdb) p data
>> $4 = (const unsigned char *) 0x15 <Address 0x15 out of bounds>
>> (gdb) p data_size
>> $5 = 1
>>
>> /////////////////////////////////////////My  
>> code/////////////////////////////////////////////////////////
>>
>> static int rarules_get_stream(struct mail * mail, struct  
>> message_size * hdr_size,
>>                               struct message_size * body_size,
>>                               struct istream ** stream_r)
>> {
>> 	struct rarules_mail * ra_mail = RARULES_MAIL_CONTEXT(mail);
>> 	struct istream * stream = NULL;
>> 	struct istream ** chunks = NULL;
>> 	const unsigned int max_chunks = 4;
>>
>> 	unsigned int i = 0;
>> 	unsigned int cnt = 0;
>> 	unsigned int exclude_cnt = 0;
>> 	unsigned int include_cnt = 0;
>>
>> 	int ret = 0;
>>
>> #if 1
>> 	{/* Test code */
>> 		const char * str = "Subject";
>> 		const char * str2 = "X-DSPAM: test value\n\n";
>>
>> 		array_append(&ra_mail->exclude_headers, &str, 1);
>> 		array_append(&ra_mail->include_headers, &str2, 1);
>> 	}
>> #endif
>>
>> 	DPRINT("Standard get_stream for mail storage format");
>> 	ret = ra_mail->module_ctx.super.get_stream(mail, hdr_size,  
>> body_size, &stream);
>>
>> 	include_cnt = array_count(&ra_mail->include_headers);
>> 	exclude_cnt = array_count(&ra_mail->exclude_headers);
>>
>> 	if ((!exclude_cnt && !include_cnt) || ret < 0) {
>> 		*stream_r = stream;
>> 		return ret;
>> 	}
>>
>> 	DPRINT("Create message from chunks with new headers and skip  
>> excluded headers");
>> 	chunks = t_new(struct istream *, max_chunks);
>> 	chunks[cnt++] = header_filter(stream, &ra_mail->exclude_headers,  
>> exclude_cnt);
>> 	if (include_cnt) {
>> 		chunks[cnt++] = create_header_stream(&ra_mail->include_headers,  
>> include_cnt);
>> 	}
>> 	chunks[cnt++] = create_stream_for_msgbody(stream);
>> 	chunks[cnt++] = NULL;
>>
>> 	*stream_r = i_stream_create_concat(chunks);
>>
>> 	DPRINT("Cleanup");
>>
>> 	array_clear(&ra_mail->include_headers);
>> 	array_clear(&ra_mail->exclude_headers);
>>
>> 	for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
>> 	i_stream_unref(&stream);
>>
>> 	DPRINTF("Func `%s' executed", __FUNCTION__);
>>
>> 	return ret;
>> }
>>
>>
>> inline static struct istream *
>> create_stream_for_msgbody(struct istream * stream)
>> {
>> 	struct istream * tmp = stream;
>> 	struct message_size hdr_size;
>> 	struct message_size body_size;
>>
>> 	DPRINTF("Func `%s' called", __FUNCTION__);
>>
>> 	message_get_body_size(stream, &body_size, NULL);
>> 	message_get_header_size(stream, &hdr_size, NULL);
>>
>> 	i_stream_seek(stream, hdr_size.physical_size);
>> 	stream = i_stream_create_limit(stream, body_size.physical_size);
>>
>> 	i_stream_unref(&tmp);
>>
>> 	return stream;
>> }
>>
>>
>> inline static struct istream *
>> header_filter(struct istream * stream, ARRAY_TYPE(const_string) *  
>> headers_arr,
>>               unsigned int count)
>> {
>> 	const char * const * headers = NULL;
>>
>> 	DPRINTF("Func `%s' called", __FUNCTION__);
>>
>> 	if (count) { headers = (const char **)array_idx(headers_arr, 0); }
>>
>> 	return i_stream_create_header_filter(stream,
>> 					     HEADER_FILTER_EXCLUDE |
>> 		                             HEADER_FILTER_NO_CR |
>> 		                             HEADER_FILTER_HIDE_BODY,
>> 					     headers,
>> 					     count,
>> 					     null_header_filter_callback,
>> 					     NULL);
>> }
>>
>>
>> inline static struct istream *
>> create_header_stream(ARRAY_TYPE(const_string) * headers_arr,  
>> unsigned int count)
>> {
>> 	unsigned int i = 0;
>> 	struct istream  * result = NULL;
>> 	struct istream ** chunks = NULL;
>> 	const char * const * headers = NULL;
>>
>> 	DPRINTF("Func `%s' called", __FUNCTION__);
>> 	i_assert(count != 0);
>>
>> 	headers = (const char **)array_idx(headers_arr, 0);
>>
>> 	DPRINT("Create streams for new included headers from headers");
>> 	chunks = t_new(struct istream *, count + 1);
>> 	for (i = 0; i < count; ++i) {
>> 		struct istream * tmp = NULL;
>>
>> 		tmp = i_stream_create_from_data(headers[i], strlen(headers[i]));
>> 		chunks[i] = i_stream_create_lf(tmp);
>> 		i_stream_unref(&tmp);
>> 	}
>> 	chunks[count] = NULL;
>> 	result = i_stream_create_concat(chunks);
>>
>> 	for (i = 0; chunks[i] != NULL; ++i) { i_stream_unref(&chunks[i]); }
>>
>> 	return result;
>> }
>>
>



More information about the dovecot mailing list