ActionMailer and Postfix Parallel Delivery

Excuse me if this has been answered before… I couldn’t find the
solution anywhere. I’m really having a problem with Postfix I believe,
but I expect the Rails community to be the friendliest source of
information, especially since I suspect someone has dealt with this
before.

I have Postfix set up to deliver all mail to a specific domain to
ActionMailer in my Rails app. This works beautifully, except for one
hitch. From what I can tell, Postfix delivers mail sent to more than
one address in parallel, meaning at the exact same time with
multiple threads. No matter what kind of checking I do in my
ActionMailer “receive” method, I cannot catch duplicate incoming
messages, thus weird things happen in my app.

Basically, I need a way to disable multi-threaded/parallel mail
delivery in Postfix, or a way to guarantee that ActionMailer will
catch duplicate messages.

Just in case this doesn’t make sense, let me explain further…

ActionMailer receives all mail for example.com and does something with
every message:

  1. John D. sends a message to both [email protected] and
    [email protected].
  2. Postfix delivers one copy of the message to ActionMailer for each
    recipient, thus the Rails app gets two copies of the message at the
    same time
    , in two completely separate running processes.

Any help with this would be greatly appreciated. I’ve tried numerous
things on the Rails side to no avail, and the Postfix docs are
confusing for me.

catch duplicate messages.

Any help with this would be greatly appreciated. I’ve tried numerous
things on the Rails side to no avail, and the Postfix docs are
confusing for me.

I’ve never piped mail into Rails before, but I’d suggest doing some sort
of “message locking” on the Message-ID header. Odds are those would be
the same in your above example.

However, I’ve received emails from some folks that are identical, but
have
a different message id header. No idea what their issue was, but it
happened.

So, you should think about how to handle that cause it’s gonna happen at
some point…

good luck.

I’ve never piped mail into Rails before, but I’d suggest doing some sort
of “message locking” on the Message-ID header. Odds are those would be
the same in your above example.

Fact is, I’ve done this sort of thing, and even as much as logging the
subject + sender to filter that way. Still, duplicate messages make
their way through simply because each copy is delivered at the exact
same time in separate processes. It doesn’t seem to matter how early
on I do the “locking” – the duplicates still make their way through
in a separate thread/process.

I’m really hoping someone knows a way to disable Postfix parallel
processing. Perhaps I’ll post my dilemma to the Postfix list. Thanks
for your help.

On Feb 23, 2007, at 10:25 PM, Tim M. wrote:

same time in separate processes. It doesn’t seem to matter how early
on I do the “locking” – the duplicates still make their way through
in a separate thread/process.

I’m really hoping someone knows a way to disable Postfix parallel
processing. Perhaps I’ll post my dilemma to the Postfix list. Thanks
for your help.

Tim-

I’d like to make a suggestion to save you some hassle. Piping each
email into a script/runner does not scale very well at all. Each
email causes a full rails process to fork and load the whole
framework. If you start to get even 10 emails a minute incoming into
a script/runner pipe you are going to start killing your server.

The better way to handle incoming mail in rails imho is to start
one rails script/runner that has acces to yoru apps env and then
have it run in a loop and have it go out and retrieve mail over pop3
or imap. This way you can poll the pop3 server every 30 seconds and
process the mail you get and then sleep, wake up and process more
mail. This scales way better then piping every mail to a new
script/runner and it will use infinitely less resources.

YMMV

Cheers-
– Ezra Z.
– Lead Rails Evangelist
[email protected]
– Engine Y., Serious Rails Hosting
– (866) 518-YARD (9273)

Thanks for the advice. I will add that to my list of to-dos for my
app, but in the meantime, I still would love a solution to this
problem. Anybody?