szabgab has asked for the wisdom of the Perl Monks concerning the following question:

In a web application, upon some actions I send e-mail to a few people. I guess in the longer term the number can go up to several 100s addresses. The messages need to be sent individually as they might have slightly different content.

I have been using Mail::Sendmail so far but I have a feeling (admittedly not measured) that it is slow. I would like to make sure the e-mails are dispatched as fast as possible with little load on the CPU.

Then, once they are dispatched they can stay in the sendmail queue till they get delivered.

What module do the monks recommend for this?

Update

The app is on a linux machine with postfix as the mailer and I am using it as the SMTP server.

Replies are listed 'Best First'.
Re: Fast dispatch of e-mails
by deorth (Scribe) on Jul 06, 2007 at 07:19 UTC
    There are many factors here that may have nothing to do with the perl modules you've chosen.

    What sizes are the message, whats the connection setup time with your mailserver, could *it* be the slow point ?

    Net::SMTP may be more lightweight, but I think you need to do measurements with both and a standard set of message mixes to know for sure. Also define your expectations. How quickly would you like one message, or ten, or one hundred sent in one go, to arrive in the MTAs queue ? Compare this same set of messages to echoing a prepared SMTP session directly to the MTA server port 25 using netcat, and see how much overhead the server accounts for, independent of your perl script or modules.

    HTH

    Alan

      Oh, I should have said that it is on a Linux box with its own sendmail (postfix) and I am injecting the messages in its queue. Well, at least I hope I do...
Re: Fast dispatch of e-mails
by clinton (Priest) on Jul 06, 2007 at 11:25 UTC
    Instead of sending mail directly from my web app, I insert the message into a table in my database, and then use a cron job to pick up the new messages and to send them. This makes your web app more responsive.

    I have no experience of Mail::Sendmail, but it looks fairly flimsy in comparison with MIME::Lite, which is my mail module of choice and has served me well.

    You don't mention what platform you're running this on, but if it is a *nix box, then you should have sendmail available to you. MIME::Lite will use sendmail to inject the mail directly into your local SMTP queue, which is fast. If not, then MIME::Lite will use Net::SMTP to send to a remote SMTP server. This will make your process slower, but if it is not happening in your web app, that's probably OK.

    Clint

      Sorry clinton, but this is really bad advice. Using MIME::Lite to run an instance of sendmail (or another MTA aliased to it) for every mail you send is far less efficent than having your app talk to a locally running MTA and send the message normally via SMTP. The overhead of starting up a new process for every message far outweighs the minimal network overhead you incur when talking to a running daemon (especiall, since on sane *NIXes the loopback address is special and hardly involves any network overhead at all).

      So my advice would be exactly the opposite, don't pipe the message to a newly started process (which is what MIME::Lite does by default), rather send it via your local mail server installation (which is what Mail::Sendmail does by default).

      Also, by inserting your message into a database and picking it up via cron you are in effect creating your own primitive version of a mail server queue. This is extremely unlikely to be as efficient and failsafe as the queueing system of the MTA, since those have been designed and improved expressly for this purpose for a number of years now.

      All of this is only true if you can run a local mail server of course (which should be possible for any serious web application).


      All dogma is stupid.
        thanks tirwhan - good points well made. I will be revising my strategy.

        Clint

Re: Fast dispatch of e-mails
by snopal (Pilgrim) on Jul 06, 2007 at 14:09 UTC

    For the record, sending mail is S-L-O-W. The communication necessary to complete a mail transport transaction is reliant on a variety of things not under your control. The biggest things not under your control is the remote site availability or response time.

    Strategically, it is much better to put the mail in a trusted delivery queue, and allow another process to invoke delivery.

Re: Fast dispatch of e-mails
by whereiskurt (Friar) on Jul 07, 2007 at 15:11 UTC

    szabgab:

    Everyone here has already made good points. My production strategy is a combination of clint's earlier post, and the comments made tirwhan.

    Background: I always want to return my webrequest as soon as possible. Sometimes the email I need to trigger out have 500k or 5MB attachments. I don't want two strategies -- one that works for really tiny emails and one that works for huge attachment emails. So I found the following to be an excellent compromise for my setup.

    Solution: Anytime my webapp needs to send out an email, a smaller descriptor email goes out to 'processemail@localhost', which is injected almost immediately. The injected descriptor email ultimately gets passed along to another process that sends out the describe email, for the webapp. The descriptor email is arbitrary and generally a tiny protocol that you create. The protocol messages shouldn't contain the attachments, but rather refer to WHERE the attachments can be attached. You could call this description email a meta-email: an email about an email (or just flame me for using the word meta instead :-)) This is generally very fast and pretty scalable.

    Once the meta-email arrives to the 'processemail@localhost' address (it didn't have to travel far) a script POSTs the email's content to a local mod_perl service at 'http://localhost/processemail'. This services creates a MIME::Lite object, assembles it from the meta-email body (as a POST value), attaches the attachments from the references, and injects the 5MB monster into a local MTA (which can take a second or two.) My local smtpd serer (the one on the webserver) then does smart forwarding to our real outbound mailer. If our outbound mailer is down, it's sits on the webservers smtpd queue as necessary. If the the webservers smtpd is down, um... we're screwed ;-)


    This strategy can rule the day if you have a robust MTA, and don't mind the size/network penalty for the descriptor emails. This strategy can also be very flexible. For example, in the descriptor email your attachments could be described as URLs which the 'processemail' server retrieves and attaches. This could then allow you to move the MTA from where the attachments are stored.

    It scales pretty well too. For example, each webserver has it's own mail queue which means its output can be throttled to slow delivery to the outbound mailer, but still return immediately to webrequests.

    Anyhow, just some more food for thought. Have a great weekend!

    Kurt