http://www.perlmonks.org?node_id=20488

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

the problem: I need to send a bunch of email without using cc, bcc or anything like that.
I would like to find a way to send an email message without closing the pipe


unfortunately I have no idea how to do this so I am stuck opening and closing sendmail for each email address in the array

any ideas ??
foreach (@mail_to) { open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!"; print SENDMAIL "To: $_ \n"; print SENDMAIL "From: csorensen\@uptimeresources.net \n"; print SENDMAIL "Subject: South African tourism survey \n"; print SENDMAIL "Content-type: text/plain \n\n"; print SENDMAIL $content; close(SENDMAIL); }

I moved the FIFO outside the loop and kept the print statements inside.. it created one MONSTER email for everyone and sent it to the first address.. oops !

Replies are listed 'Best First'.
RE: eof without closing the pipe
by cleen (Pilgrim) on Jun 30, 2000 at 07:30 UTC
    I know Im going to get flamed for this becuase Im not using a module, but its quick and it works, plus that its quicker becuase it doesnt even open up a pipe..It uses a simple socket connection to a sendmail server (just one)
    #!/usr/bin/perl use strict; use Socket; my @users=('email1@server.com', 'email2@server.com', 'email3@server.co +m'); my $mailhost="localhost"; my $myemail="mark\@cidera.com"; # Your email address # this is just the subject and body of the message # you can get this information from anywhere I just # put it in here for the sake of example my $subject= "hi"; my $data = "hi hi hi hi there"; my $userz; socket(MAIL,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect(MAIL,sockaddr_in(25,inet_aton($mailhost))); select(MAIL); $|=1; select('stdout'); print MAIL "HELO blah.com\n"; foreach $userz (<@users>) { print MAIL "MAIL FROM: $myemail\n"; print MAIL "RCPT TO: $userz\n"; print MAIL "DATA\n"; print MAIL "Subject: $subject\n"; print MAIL "$data\n"; print MAIL ".\n"; } print MAIL "quit\n"; close(MAIL);
    This works becuase it doesnt quit the sendmail connection till after all the emails have been sent to each person in your @users array seperatly.

    I know this isnt EXACTLY what you were looking for, but its just another way to do this.
      It's nice to see someone else who uses socket (not socket.pm) and knows a protocol or two.
      now, maybe i am mistaken... however, opening up a socket connection, no matter how simple, should be MARKEDLY slower than opening up a pipe, no matter what the situation. If you are opening up a socket to a host you have to deal with:
      • TCP/IP overhead
      • Network Transport Layer Overhead
      • Communicational Latency
      • The fact that you are communicating via external means, instead of the bus!
      however, if you are opening up a pipe, to a process on the local machine then the situation is:
      • there is NO TCP/IP overhead
      • there is NO network layer overhead
      • the communicational latency is the velocity at which the receiving process can aquire STDIN
      • and you are communicating through memory and the bus, which have a MUCH greater bandwith and throughput than most any network connection!
      if speed is your constraint, and you are attempting to maximize the throughput (here being messages per minute) I can not conceive of a way faster than communicating directly with sendmail through a pipe.

      UPDATE: thanks to lhoward i have now learned that in modern operating systems, much to my suprise, the TCP subsystem has been optimized WAY better than I ever thought it would be, so, my entire coment above, should be disreguarded and i should be flogged for not having benchmarked in the first place :) keep the learning coming...

        Opening a socket is typically as fast or faster than opening a pipe.

        Pipe issues:

        • Have the overhead of starting a separate process. (you may or may not have this overhead when doing a TCP socket connection depending on if the server is forking or threading)
        socket/TCP port issues:
        • Most OSes have highly optimized TCP/IP stacks, generally much more optmized than the OSes core pipe processing functions. For today's applications network performance is typically much more important than pipe performance.
        • localhost TCP/IP connections (where client and server are on the same host) do not go out "on the wire", they are typically highly optimized with direct memory-to-memory exchange of the data. Localhost network connections have practially 0 network overhead.
      I will not flame you. Looks like a nice way to do the job. There is not many who speak "natively" with sendmail nowdays ;)

      /brother t0mas
Re: eof without closing the pipe
by chromatic (Archbishop) on Jun 30, 2000 at 01:36 UTC
    The author of Mail::Bulkmail claims it can process at least 884 messages per minute. If you promise your intentions are noble, have a look at that module.
      thanks .. people have mentioned that module to me before. I was hoping that someone knew a command that sent "eof" or something similiar to sendmail.
Re: eof without closing the pipe
by Shendal (Hermit) on Jun 30, 2000 at 00:56 UTC
    How about this:
    open(SENDMAIL"|$sendmail") or die "Cannot open $sendmail: $!"; print SENDMAIL "To: " . join ",",@mail_to . "\n"; print SENDMAIL "From: csorensen\@uptimeresources.net \n"; print SENDMAIL "Subject: South African tourism survey \n"; print SENDMAIL "Content-type: text/plain \n\n"; print SENDMAIL $content; close(SENDMAIL);
      Would this join create an enormously fat To: line that would get sent to everybody in it or does it do something more subtle?

      -PipTigger

      p.s. Initiate Nail Removal Immediately!
        It would create an enormously fat To: line. I guess you could use bcc to hide that, but the original question didn't want to use bcc. Another choice is using bulkmail, which has already been suggested by someone else.