# Exim mail filter in ruby

**URL:** <https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144>\
**Category:** Ruby\
**Created:** [November 30, 2005, 5:43pm UTC](https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144 "2005-11-30T17:43:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrisjroos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/43a26b/32.png) [@chrisjroos](https://www.ruby-forum.com/u/chrisjroos)\
**Post date:** [November 30, 2005, 5:43pm UTC](https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144/1 "2005-11-30T17:43:18Z")

</div>

Hi,

I have a requirement to create a shell script that accepts data on it’s  
standard input, calls another shell script (out of my control), passing  
an amended copy of the original input, and collects anything sent to  
stderr and stdout by the external script. This shell script is to be  
used as a mail filter being called from exim.

I got a basic version working using Kernel.open but got very confused  
when trying to trap the output of that external script (stderr and  
stdout).

The best looking code was produced when using Session[1] but that  
started causing me problems too - it looked as though either my parent  
or child process didn’t wait until the other finished (i.e. i could see  
the logged output not following the expected program flow; I fully  
expect this to be something I was doing wrong).

I am now using open3 which is working but feels a little fragile,  
although that’s probably completely unfounded.

I guess I’m really asking for other peoples approaches to similar  
problems. My concerns really arise from the fact that I’m not able to  
fully test the interaction of this process (or at least not easily).  
Does anyone have any tips regarding shell scripting with pipes / forks  
/ all the other things I don’t really understand?

Chris

[1] [http://www.codeforpeople.com/lib/ruby/session/](http://www.codeforpeople.com/lib/ruby/session/)

---

<div class="post-metadata">

**Author:** ![chrisjroos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/43a26b/32.png) [@chrisjroos](https://www.ruby-forum.com/u/chrisjroos)\
**Post date:** [November 30, 2005, 6:03pm UTC](https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144/2 "2005-11-30T18:03:34Z")

</div>

On Thu, 1 Dec 2005, removed\_email\_address@domain.invalid wrote:

> Hi,
> 
> I have a requirement to create a shell script that accepts data on it’s  
> standard input, calls another shell script (out of my control), passing  
> an amended copy of the original input, and collects anything sent to  
> stderr and stdout by the external script. This shell script is to be  
> used as a mail filter being called from exim.

I don’t find this description very clear. Which part of exim are  
you using to do this? That might help me understand.

> I got a basic version working using Kernel.open but got very confused  
> when trying to trap the output of that external script (stderr and  
> stdout).

What about using the shell in popen("/bin/sh command 2\>&1", “r+”) ?

The stdout and stderr are combined, but you can still write to it.

```
    Hugh
```

---

<div class="post-metadata">

**Author:** ![chrisjroos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/43a26b/32.png) [@chrisjroos](https://www.ruby-forum.com/u/chrisjroos)\
**Post date:** [November 30, 2005, 6:56pm UTC](https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144/3 "2005-11-30T18:56:16Z")

</div>

In exim, I create a transport that uses a pipe to send the email to my  
shell script. I also create a router that sends every mail that exim  
processes to my transport (providing I haven’t already processed it).

My shell script reads the email from stdin and parses it based on some  
custom rules.

If it passes the rule checks it can be sent back into exim. This is  
achieved by writing to the stdin of the exim command with some  
additional parameters. Once I’ve given the email back to exim, I want  
to check for data on it’s (exim command) stdout and stderr so that I  
can log any problems.

The interaction with exim is straight from the exim book and all works  
ok. The question I have is really about the best way to deal with  
piping data to/from different processes within ruby in addition to  
trying to understand what’s going on better.

I did use IO.popen to start with and can’t now remember the problems I  
had, probably just ignorance on my part…

Chris

---

<div class="post-metadata">

**Author:** ![chrisjroos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/43a26b/32.png) [@chrisjroos](https://www.ruby-forum.com/u/chrisjroos)\
**Post date:** [November 30, 2005, 9:02pm UTC](https://www.ruby-forum.com/t/exim-mail-filter-in-ruby/49144/4 "2005-11-30T21:02:05Z")

</div>

On Thu, 1 Dec 2005, removed\_email\_address@domain.invalid wrote:

> to check for data on it’s (exim command) stdout and stderr so that I  
> can log any problems.

OK, sounds pretty std.

> The interaction with exim is straight from the exim book and all works  
> ok. The question I have is really about the best way to deal with  
> piping data to/from different processes within ruby in addition to  
> trying to understand what’s going on better.

I needed to understand where the data was flowing: that’s why I  
asked about how it interacted with exim.

> I did use IO.popen to start with and can’t now remember the problems I  
> had, probably just ignorance on my part…

then I think what I wrote should work. Maybe give it a spin or  
compare it to the version you used unless you threw it out already  
🙂

> Chris

```
    Hugh
```
