Exim: Creating and using Macros

The topic looks easy, but implementing them was a great learning experience, as I found it. Macros helps to make reuse a lot of code, and make the exim configuration look tidy. In the earlier post, I scribbled how to define an Exim regex to capture all VERPed emails as :

begin routers

mw_verp_api:
	driver = accept
	domains = +local_domains
	condition = ${if match{$local_part}{^bounces-\w+-\w+-\w+-\w+$}{true}{false}}
	transport = mwverpbounceprocessor

and under transports:

mwverpbounceprocessor:
	driver = pipe
	command = /usr/bin/curl -H 'Host: <%= @verp_post_connect_server %>' <%=@verp_bounce_post_url
	%> -d "action=bouncehandler" --data-urlencode"email@-"
	user = nobody
	group = nogroup

Tidying this up a bit, we can make something like:


#Under main configurations 
VERP_BOUNCE_LOCALPART_REGEXP = ^bounces-\w+-\w+-\w+-\w+$
VERP_BOUNCE_POST_URL = http://localhost/api.php

mw_verp_api:
	driver = accept
	domains = +local_domains
	condition = ${if match{$local_part}{VERP_BOUNCE_LOCALPART_REGEXP}{true}{false}}
        transport = mwverpbounceprocessor

and under transports

mwverpbounceprocessor:
	driver = pipe
	command = /usr/bin/curl action=bouncehandler --data-urlencode email@- VERP_BOUNCE_POST_URL
	user = nobody
	group = nogroup

Hope it helps someone tidy-code 😀

Exim regex: Capture all VERPed emails with a given header pattern

Consider your VERP generater produces a Return-Path header of the form:
bounces-testwiki-2a-nanrfx-Tn14EQZWaotS2XNn@mytesthost.com
and you want a router to capture all bounce emails having this/similar as the To header. This router can serve multiple purpose like – feeding to a bounce processor, silently killing all bounces ( not intended ) or POSTing the email to an API.
Suppose you have a router named bounceprocessor that HTTP POST to an API named bouncehandler at localhost/api.php, we will design the Regex as:

begin routers

bounceprocessor:
	driver = pipe
	domains = +local_domains
	condition = ${if match{$local_part}{^bounces-\w+-\w+-\w+-\w+$}{true}{false}}
	command = /usr/bin/curl "action=bouncehandler" --data-urlencode "email@-" http://localhost/api.php
	user = nobody
	group = nogroup

Please note that

\w = words 
\d = digits 

Thanks to Mark Bergsma and Jeff Green for helping me with the regex.

POST-ing bounce email to a Mediawiki API directly from exim

While moving forward with the BounceHandler extension, I was advised by my mentors to make sure that the bounce emails are directly fed to an API inside the extension, so that no manual queries are required, and its more safe.
An API, with the name foo can be accessed in the URL by http://localhost/mw-core/api.php?action=foo. A POST request with the name bar can be sent by URL http://localhost/mw-core/api.php?action=foo&bar=value
* How to add the new API
In your extension.php, register the new API, named bouncehandler firstly by:

$wgAutoloadClasses['ApiBounceHandler'] = $dir. '/ApiBounceHandler.php';
$wgAPIModules['bouncehandler'] = 'ApiBounceHandler';

* Make exim forward the emails directly to the API. Put this under the appropriate pipe transport.

command = /usr/bin/curl http://localhost/core/core/api.php -d "action=bouncehandler" --data-urlencode "email@-" -o /dev/null

or this can be done in a shell script too. You can direct the command to the shell script.

command = /path/to/script.sh

and in the script.sh

#!/bin/bash
curl -d &amp;quot;action=bouncehandler&amp;quot; --data-urlencode &amp;quot;email@-&amp;quot; http://localhost/core/mw-core/api.php

* Now, on reception of a mail, it gets automatically transferred to the API, with the email as a POST param. The generated POST url will be of the form http://localhost/core/mw-core/api.php?action=bouncehandler&email=the_email
* You can recieve the email POST param in the API by

class ApiBounceHandler extends ApiBase {
	public function execute() {
             $email = $this-&gt;getMain()-&gt;getVal( 'email' );
        }
}

Yay! further handling of the emails coming up in next post! 🙂 Happy Hacking!

Forwarding mails to a PHP script with exim4

Forwarding mails to a script enables the Mail admin to work around with the incoming email a bit, before it gets delivered. A VERP address check, destination or sender address extraction, SPAM checks, and a lot more can be done by these e-mail parsing.
Problem:
* You have a mail addressed to root@localmac and you need to get it directed to a script, located at /var/mail/script.php
* You have exim4 running on port25
* You have got root : root in /etc/aliases – meaning emails to root get delivered to root.
* You have got domainlist local_domains = +system_domains in your exim4.conf
Solution:
Just to start from the basics:
* add the following to the /etc/exim4.conf

under begin_routers:

# Use the system aliasfile /etc/aliases for system domains
system_aliases:
	driver = accept
	domains = +local_domains
	transport = use_pipe

under begin_transport:

use_pipe:
	debug_print = " Using the pipe transport"
	driver = pipe
	command = /etc/exim4/script.php
	return_path_add
  	delivery_date_add
	envelope_to_add
	return_output

Now, exim is good to go. Thinking of what you will put up in the script.php ?
You can always find it here https://github.com/tonythomas01/exim4box1verp/blob/piped/script.php
Now, test the entire settings by :

# exim -bt root@localmac
>root@localmac
>router = system_aliases, transport = use_pipe
# mail -s "Subject" root@localmac
Type the body here. Click ctrl+D to quit
now check in the exim logs
# nano /var/log/exim4/mainlog It will have something like

2014-06-06 18:49:06 1WszCM-000360-D6 root R=system_aliases T=use_pipe
2014-06-06 18:49:06 1WszCM-000360-D6 Completed

The message_id, date and time will vary though 😛
PS:- This looks like my B’day post. I am 20 🙂