Ubuntu Postfix Pipe to C++ Program to Capture Your Email

How to grab the contents of an email to your virtual address and save it to a file

By Robin Rowe

HOLLYWOOD, CA (LinuxMovies) 2015/10/24 – Sometimes you’d like to take full control of emails sent to an address on your Postfix mail server. For example, you may have set up your version control system to automatically send you emails on updates and you wish to also store that information to a database or do some something else with it.

The do-something-with-it-after part may seem easy enough, but how do you capture the contents of that email as it passes through Postfix?

In this how-to we’ll show how to capture a Postfix email and write it to a file using Postfix and C++.

Simple Postfix Filter Program

First, let’s write a little filter in C++ that captures stdin and writes it to a file. We could have written this in bash, Perl or whatever, but I prefer C++.

// postfix_filter.cpp Simply writes stdin to a file
// Copyright Robin.Rowe@CinePaint.org 2015/10/22
// License MIT or BSD

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{   const unsigned bufsize=1024;
    char buffer[bufsize];
    const char* filename="/data/filter/mail_filter_test.txt";
    const int flags=O_CREAT | O_WRONLY;
    mode_t mode = S_IRUSR | S_IWUSR;
    const int out = open(filename,flags,mode);
    if(out<=0)
    {   return 1;
    }
    for(;;)
    {   const ssize_t bytes=read(STDIN_FILENO, buffer, sizeof(buffer));
        if(bytes<=0)
        { break;
        }
        write(out,buffer,bytes);
    }
    close(out);
    return 0;
}

To build this we call…

 make postfix_filter

No need to write a make file for this. The built-in make rules are sufficient.

Updating Newaliases

Next let’s add an alias to pipe emails to our filter.

vi /etc/aliases

my_filter: |/home/user/filter/postfix_filter

Save this file and update OS with…

newaliases

Updating virtual_alias_maps

Next let’s add our virtual email address…

vi /etc/postfix/virtual_alias_maps

capture@example.com my_filter@localhost

Save and update Postfix…

/usr/sbin/postmap /etc/postfix/virtual_alias_maps
/usr/sbin/postfix reload

Testing Email Capture

Send an email to your capture@example.com server address. If a file appears at /data/filter/mail_filter_test.txt, great. If not, tail /var/log/mail.log to see what the error message is.

Make sure you have set permissions such that postfix, running as nobody, can see and execute your filter. That’s probably the issue if your error log says it can’t find your filter or that it returned 1 (couldn’t write the output file).

An unlikely possibility is that main.cf isn’t configured for newalises, that somebody changed it from the standard Ubuntu configuration.

You can test your postfix_filter in isolation without Postfix by simply calling it from the command line. Type in whatever test input you like, then press enter and CTRL-D to close stdin. What you typed should appear as mail_filter_test.txt.

Running this little test program proves you’ve mastered piping email from Postfix to your own filter program. Now you can write a more sophisticated filter that does something more useful than dumping the last email sent to an address to a file.

Leave a Reply

Your email address will not be published. Required fields are marked *