odmrd

quick link: odmrd History

What is ODMR?

See RFC 2465 for the complete answer.

In short:
It nearly perfectly fits in a common setup (at least in Germany): ISP that hosts website and mail, SOHO client with a mail server and a cheap internet connection (DSL, cable or similar) without static IP address.

ODMR is "SMTP with Dynamic IP Addresses". It uses an "Authenticated TURN" (ATRN) instead of ESMTP's "Extended TURN" (ETRN) to deliver queued mail to a mailserver with a dynamic IP address (ETRN delivers only to fixed IPs). There is usually an ODMR-client that passes the connection to the local SMTP-server. You don't have to redirect ports on your firewall, there is only a single connection from your mailserver to the ISPs odmr server.
You don't have to use POP3 to deliver mail for a whole domain to your clients, with all its downsides (e.g. losing the SMTP envelope information). Authentication is done via ESMTP's AUTH with CRAM-MD5, so your authentication information is reasonably protected against wiretapping (and possibly even against MITM-attacks).

What software supports ODMR?

Any mailserver that speaks SMTP should work with these clients: There are also some other odmr-servers (in no particular order). If you know about any other software, please let me know. There are few providers that support odmr (in no particular order). If you know about more or want yours listed, let me know. (Don't know why they are almost all in the UK...)

What is odmrd?

odmrd is a Perl script. You can either run it through (x)inetd/tcpserver or as a standalone daemon.
It was written in Perl mainly because an ODMR server seemed to be a good start to get some Perl experience. Perl is quite easier and safer to code than C. Strings, arrays, hashes etc. are natively supported. I planned to rewrite it in C, but it will probably not happen in the near future. The main advantage of a C version would be performance, but that was no problem during my tests (may be a concern in very large setups, though).

Some facts about odmrd (aka features):

So what do I need for odmrd?

odmrd is intended to run on a unix-like system (uses /proc interface). It was developed and tested on RedHat 7.x machines with Exim 3.3x, MySQL 3.23.3x, Perl 5.6.x, the current version runs on Fedora Core 1 (Perl 5.8.0).
You need

How does it work?

A mysql database is used to store the ODMR domains and the corresponding users (one user per domain, multiple domains per user). The same database is used by the MTA, so he knows which domains it should accept mail for (incoming) and the authentication information for relaying your user's mail (outgoing). The messages are stored in the file system by the MTA and picked up by odmrd when a user wants to get his mail.

How do I setup odmrd?

1. Prepare your mailserver

By default odmrd searches messages in domain-seperated files stored in /var/spool/odmr/$domain/, so you should setup your mailserver to deliver via BSMTP (batch SMTP). The files should look like this:
MAIL FROM:<some_user@example.com>
RCPT TO:<another.user@example.net>
DATA
Received: ....
From: ....

blabla
.
All lines should be terminated by CRLF.

Exim

With Exim you can do it this way:
Version 3 (old, you should upgrade to 4)
# MAIN CONFIGURATION SETTINGS

# mysql configuration, set your own parameters here
hide mysql_servers = localhost/mail/exim/secret

local_domains = [...]:mysql;SELECT domain FROM odmr.domain WHERE domain = '${quote_mysql:key}'


# TRANSPORTS CONFIGURATION

# Store mails in domain-directories for ODMR
odmr:
  driver = appendfile
  directory = /var/spool/odmr/$domain
  bsmtp = domain
  use_crlf = true
  prefix =
  suffix =
  user = odmr
  group = odmr


# DIRECTORS CONFIGURATION

odmr_domains:
  driver = smartuser
  transport = odmr
  domains = mysql;SELECT domain FROM odmr.domain WHERE domain = '$domain'
(Note: It is possibly not really clean to consider odmr domains as local and handle them via the smartuser director. I think it would be better to use a router, but it works flawless this way.)
Version 4
### main configuration ###

# mysql configuration, set your own parameters here
hide mysql_servers = localhost/mail/exim/secret

domainlist relay_to_domains = mysql;SELECT domain FROM odmr.domain WHERE domain = '${quote_mysql:$domain}'


[...]
begin routers

odmr_router:
 driver = accept
 domains = mysql;SELECT domain FROM odmr.domain WHERE domain = '${quote_mysql:$domain}'
 transport = odmr_transport

[...]
begin transports

odmr_transport:
 driver = appendfile
 directory = /var/spool/odmr/$domain
 use_crlf
 use_bsmtp
 batch_max = 1000
 user = odmr
 group = odmr
If you want your Exim server to relay mail from your ODMR users, tell them to use SMTP authentication and put this into your configuration (works with Exim 3 and 4, for Exim 3 you need host_auth_accept_relay = *):
begin authenticators

# CRAM-MD5
# used by: Eudora
cram_md5:
  driver = cram_md5
  public_name = CRAM-MD5
  server_set_id = $1
  server_secret = ${lookup mysql{ \
        SELECT pass FROM odmr.user \
        WHERE user = '${quote_mysql:$1}'} \
       {$value}fail}

# C: AUTH LOGIN [base64($user, \0, $pass)]
# - if no authentication on AUTH LOGIN:
# S: base64('Username:'), C: base64($user)
# S: base64('Password:'), C: base64($pass)
# Used by: Outlook Express
login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_set_id = $1
  server_condition = ${if eq\
        {$2} \
        {${lookup mysql { \
          SELECT pass FROM odmr.user \
          WHERE user = '${quote_mysql:$1}' \
        }{$value}fail}} \
        {1}{0}}

# C: AUTH PLAIN base64(\0, $user, \0, $pass)
# used by: Netscape
plain:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :
  server_set_id = $2
  server_condition = ${if eq \
        {$3} \
        {${lookup mysql { \
          SELECT pass FROM odmr.user \
          WHERE user = '${quote_mysql:$2}' \
        }{$value}fail}} \
        {1}{0}}

Postfix

Postfix does not seem to speek BSMTP natively, so you need this script and the following in your master.cf:
odmr     unix  -       n       n       -       -       pipe
        flags=h. user=odmr:odmr eol=\r\n argv=/usr/local/sbin/odmrspool.pl -f ${sender} -t ${nexthop}  ${recipient}
(By courtesy of Chris Hastie, correction by Paul Lange)

2. Create a database

The intended name of the database is 'odmr' but any name will do it. For ease of use, I use the same database for odmrd and vmail-sql/tpop3d. In my newer Exim4 setup I seperated the databases and choose the right one in my queries.
CREATE DATABASE odmr;
USE odmr;

# Table structure for table 'odmr_user'
CREATE TABLE user (
  user varchar(30) NOT NULL default '',
  pass varchar(15) NOT NULL default '',
  PRIMARY KEY  (user)
) ENGINE=INNODB;

# Table structure for table 'odmr_domains'
CREATE TABLE domain (
  domain varchar(64) NOT NULL default '',
  user varchar(30) NOT NULL default '',
  PRIMARY KEY (domain),
  KEY user (user),
  FOREIGN KEY (user) REFERENCES user(user)
) ENGINE=INNODB;
Populate the table user with your designated ODMR clients (the usernames are up to you) and the table domain with the domains you want to relay mail for and the corresponding user. Example:
use odmr;
INSERT INTO user (user, pass) VALUES ('user1', 'pass1'), ('user2', 'pass2');
INSERT INTO domain (domain, user) VALUES ('example.net', 'user1'), ('example.org', 'user1'), ('example.com', 'user2');
This essentialy means:

2.1 Accounting

If you want accounting you need a third table:
CREATE TABLE acct (
  user varchar(30) NOT NULL default '',
  date int(10) unsigned NOT NULL default '0',
  b_in int(10) unsigned NOT NULL default '0',
  b_out int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (user,date)
) TYPE=MyISAM;
To retrieve the accounting information, I use this script:
#!/bin/sh
MONTH=${1:-$(date +%Y%m)};
mysql -t -uUSERNAME -pPASSWORD DATABASE -e "SELECT user, SUM(b_in)/1024/1024 'm in', SUM(b_out)/1024/1024 'm out', (SUM(b_in)+SUM(b_out))/1024/1024 'm total' FROM odmr_acct WHERE date BETWEEN '${MONTH}00' AND '${MONTH}99' GROUP BY user"
and this in the crontab:
1 0 1 * *  acct-odmr.sh `/bin/date -d "last month" +\%Y\%m` | mail -s "odmr-acct" accounting@your-domain.org

3. Setup server

If it's not already there, put this in your /etc/services:
odmr            366/tcp                         # On Demand Mail Relay Protocol

3.1 inetd-mode

3.2. Standalone mode (since 0.9)

4. Install and configure odmrd

Create a group odmr and a user odmr with rwx-rights to the odmr spool directory (/var/spool/odmr). Copy odmrd to /usr/local/sbin. If this is a new installation, copy the sample odmrd.conf to /etc and modify it to your needs (should be self-explaining). You have to change at least mysql_pass.

5. Secure your system (optional but strongly recommended)

These are the things that come to my mind just at this moment:
odmrd needs rwx-rights to the spool-directory to create its lockfiles (maybe they will be moved to another directory in a future release) and to the subdirectories to read and delete messages. odmrd needs SELECT-rights to odmr_user and odmr_domains and SELECT, INSERT, UPDATE rights to odmr_acct.

6. Enjoy it.

Mail me if there are any problems, you have suggestions or anything else. Mail me that you are using this programm.

Miscellaneous

License and disclaimer

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

The Past: History

Version 0.5

Version 0.6

2002-08-03: Version 0.7 released

2003-06-06: Version 0.8 released

2004-03-13: added some information on the website for Exim 4 and relaying after SMTP-Auth

2004-07-25: Version 0.9rc1b released

2004-08-24: Version 0.9rc2 released

2004-08-31: The mailing list is finally set up, subscribe here.

2004-08-31: Version 0.9rc3 released

2004-09-28: Version 0.9rc5 released

2005-02-11

To the postfix users: You should add "h" to to the flags of odmrspool.pl in your master.cf to make postfix lower-case the domain name. (Thanks to Paul Lange for the hint)
Anyway, odmrspool.pl should handle this, so I changed it to use lower-case domain directories.

2005-03-12: Version 0.9rc6 released

Unrelated to this release, I changed the mailing list software. The fancy web interface is gone, you can now subscribe, unsubscribe and get help by mail.

2005-05-19: Version 0.9rc9 released

Changed odmrspool.pl so that empty sender (like used in bounce messages) are allowed.

2005-07-18: Version 0.9rc10 released

2005-07-31: Version 0.9rc12 released

2005-12-11: Version 0.9rc13 released

2005-12-12: Version 0.9rc14 released

2005-12-14: Version 0.9rc15 released

2006-06-24: some patches from Pascal Lengard and Olivier Jourdat

2008-07-05

The Future: Todo

Any hints/wishes? Mail me

Created: 2002-07-29. Last change: 2005-12-14