Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

writing a basic bulkmailer

by schweini (Friar)
on Sep 23, 2005 at 02:13 UTC ( [id://494371]=perlquestion: print w/replies, xml ) Need Help??

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

esteemed monks,

so, mailman is finally causing unbearable load on my little server because of a rather active one-way mailinglist with 8000 members that get a 300kb mail each (are loads > 3 normal on a 2GHz processor because of this, by the way? why do mailman's python processes use incredible amounts of RAM even when nobody's using them?)

So i decided to write my own little bulkmailer that simply mails a file that was received via some .forward or .qmail to a list of people registered in a mysql table.
I don't think i'm reinventing too many wheels doing this, since i want very fine-grained information on the progress of any on-going mailing, and need very customizable throttle-control, so that i can tune the script until i can rest assured that there will be no load-spikes no matter what my crazy clients think everybody should know (it's not spam, obviously).

So, my plan up to now is to do the following:

  • have a minimalistic script receive the complete email via STDIN by using .forward or .qmail files. this script simply stores the email source, unaltered, somewhere on disk, stores the filename in a mysql table, and sends a confirmation mail to the owner of the list, asking him to click on a link in order to start the sending process.
  • behind the above mentioned link is a a CGI script that, upon confirmation by the list's owner, fires off another perl script that goes into a daemon-esque mode and actually sends the mails
  • this 'sender' program reads in the email source from a file, deletes the 'To:' line in the header, opens a SMTP connection, { slaps the receiver's email address ontop of the message source and sends it to the SMTP server } foreach list member

    now, i have a couple of doubts:

  • what is the 'correct' way to start a long-running program from a CGI script? ( exec()|system() ) and detaching from STD(IN|OUT|ERR)? some kind of fork? letting some other, cron-run program check whether there are pending mailings, and start the daemon from there instead of from the CGI (the CGI script runs as apache or nobody, which might pose problems later on?)
  • would simply deleting the 'To:' line of the email's source, and slapping on a custom 'To:' for each receipient, and handing that of to SMTP be enough for what i am trying to accomplish? (one 'To:' per email - not 8000 per email, as one might read)
  • how do i send these emails? should i inject them directly into qmail's queue (how?), send them directly via Net::SMTP to the receiver's server, or should i connect to localhost's SMTP server using any of the standard modules, and let that SMTP server handle the rest?

    I'm still looking into using the great Mail::Bulkmail, but it seems almost too powerful, and i can't seem to find a way to have some 'callback' called after each mail so that i can update progress information, handle errors, etc.
  • Replies are listed 'Best First'.
    Re: writing a basic bulkmailer
    by diotalevi (Canon) on Sep 23, 2005 at 03:30 UTC
      Before you write your own version of a Mail::Bulkmail, learn to use the one that's already on CPAN. Patch it if it doesn't do what you need. Pay someone if you can't patch it yourself. Heck, talk to the author about what you want to do that can't. Don't waste your time writing something new from scratch. That's purely a waste.
        Yea, sorry. You are of course completely right.
        After posting this node, i took Mail::Bulkmail home with me and dug into the code, and i am extremly impressed on how clean and nice it is, so i'll take that route. I blame the lack of caffeine. :-)

        but i still have that question about daemonizing: after forking and closing STDOUT, IN and ERR, apache does 'let go" of the CGI script's child process, but in perlipc it says something about POSIX::setsid. what does that exactly do, and is it required?

        thanks for the wake-up call. This node was really kinda superfluous.
    Re: writing a basic bulkmailer
    by sauoq (Abbot) on Sep 23, 2005 at 02:37 UTC
      So i decided to write my own little bulkmailer that simply mails a file that was received via some .forward or .qmail to a list of people registered in a mysql table.

      If you are using qmail anyway, you might want to consider switching to ezmlm or ezmlm-idx.

      "My two cents aren't worth a dime.";
    Re: writing a basic bulkmailer
    by Zaxo (Archbishop) on Sep 24, 2005 at 01:34 UTC

      POSIX::setsid() is to free the process from a controlling terminal, making itelf a process group leader - no more parent process.

      Proc::Daemon will do exactly what you want.

      After Compline,

    Log In?

    What's my password?
    Create A New User
    Domain Nodelet?
    Node Status?
    node history
    Node Type: perlquestion [id://494371]
    Approved by GrandFather
    and the web crawler heard nothing...

    How do I use this?Last hourOther CB clients
    Other Users?
    Others imbibing at the Monastery: (6)
    As of 2024-04-17 16:26 GMT
    Find Nodes?
      Voting Booth?

      No recent polls found