in reply to Re^3: Using Threads For Simple SMTP Relay Server
in thread Using Threads For Simple SMTP Relay Server
# sub process { sub get_message { my $self = shift; my($cmd, @args); my $sock = $self->{SOCK}; $self->_reset0; print $sock "STUFF1\r\n"; while(<$sock>) { print $sock "STUFF2\r\n"; print "$$ command: $_"; ... rest of routine
The output (from the perspective of the client is:
Net::SMTP>>> Net::SMTP(2.31) Net::SMTP>>> Net::Cmd(2.29) Net::SMTP>>> Exporter(5.60) Net::SMTP>>> IO::Socket::INET(1.31) Net::SMTP>>> IO::Socket(1.30) Net::SMTP>>> IO::Handle(1.27) Net::SMTP=GLOB(0x20f758c)<<< 220 Debatable SMTP 0.2 Ready. Net::SMTP=GLOB(0x20f758c)>>> EHLO localhost.localdomain Net::SMTP=GLOB(0x20f758c)<<< STUFF1
In other words it only writes to the client the first time (it never sends STUFF2 to the client). Once the socket is read from writes aren't happening in other words. It is perplexing.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^5: Using Threads For Simple SMTP Relay Server
by BrowserUk (Patriarch) on Oct 30, 2007 at 02:53 UTC | |
Looking at Net::SMTP::Server::Client2, subclassing it is non-trivial because it uses a lexical dispatch table to invoke most of the methods you would want to override. As the dispatch table is built at compile time, overriding those methods in the usual way doesn't work. Here's one way to do it, though I shall post a SoPW to see if anyone knows a better way. The first thing you need is access to the dispatch table from within the subclass. To facilitate that, I added a class method to Client2.pm:
Then a simple subclass that overrides the HELO and HELP commands looks like this:
Not hugely elegant, but it requires the minimum change to Client2. Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
by lamberms (Sexton) on Oct 30, 2007 at 13:23 UTC | |
Here is code using the Client3 library that uses fork:
Here is the output when I send mail via this code:
As you can see the email is sent properly. Here is the code I'm trying to use and having problems with:
The only difference is that I'm treating the IO::Socket like an integer handle (This worked flawlessly for you as noted above). Here is the result of that code for me:
Here you can see that it never get EHLO command. The client receives the 220 Debatable SMTP message so it is obvious that the socket is Read Write. However, once it starts reading data from the client (EHLO commands) it is sending Welcome messages but they are never received by the other side. It is really weird that this code works on your system and does not work on mine. | [reply] [d/l] [select] |
by BrowserUk (Patriarch) on Oct 30, 2007 at 22:17 UTC | |
Two questions: Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
by lamberms (Sexton) on Oct 31, 2007 at 12:41 UTC | |
by BrowserUk (Patriarch) on Oct 31, 2007 at 13:55 UTC | |
| |
|
Re^5: Using Threads For Simple SMTP Relay Server
by BrowserUk (Patriarch) on Oct 29, 2007 at 23:32 UTC | |
In other words it only writes to the client the first time (it never sends STUFF2 to the client). Once the socket is read from writes aren't happening in other words. It is perplexing. It's not perplexing at all. Your modifications are breaking the well defined SMTP protocol. You should not be modifying the get_message() method. And you certainly should not be writing to the socket within the read loop. The get_message() method is intended to, and *must*, be called as an atomic operation in order that the rules governing the protocol will be maintained. What is happening is that you are writing to the socket at inappropriate points within the protocol exchange. The client, which is expecting the server to follow those rules, is being sent data when it is not expecting it. That breaks the protocol and the whole exchange gets screwed up. In order to make the changes you require, you should be leaving the Client2 get_message() method untouched and only modify the command handlers. You could do this by C&Ping the whole module and then modifying the individial command handler subroutines, ie. those subs whose addresses are stored in the dispatch table:
Alternatively, you could write your Client3 module as a subclass of the Client2 code and override (just) those routines you need to modify, through inheritance. Either way, the keys to that dispatch table are the only commands that the SMTP protocol understands and its values are the subroutines that will be invoked when a properly conformant command message is received from the client. And it is those routines that you should be modifying or overiding. Obviously, there are some changes to the get_message() method that might be appropriate, like sending log messages to a system log handler rather than the console, but even that could be achieved through redirecting STDOUT in a subclass. In general, you should leave the existing read loop untouched. Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |