Search code examples
bashtelnet

Telnet smtp command bash 2.05 script problem


Line by line works but in script it does not.

I tried everything i could think of.

This does not work in bash 2.05

  { sleep 1; echo "helo localhost"; sleep 1; echo "mail from: [email protected]"; sleep 1; echo "rcpt to: [email protected]"; sleep 1; echo "data"; sleep 1; echo "subject: test"; echo; echo "some text" ;echo "."; echo "quit"; } | telnet mailserver.actualdomain.org 25

but if you do line by line

telnet mailserver.actualdomain.org 25
220...
helo localhost
250...ok
mail from: [email protected]
250..ok
rcpt to: [email protected]
250...ok
data
354 Start mail input; end with <CRLF>.<CRLF>
subject: test

some text
.
quit

then it works and i get mail. the script works in newer bash 4.4 but i need it to work in 2.05. seems to me that it does not do echo "." et the end and does not finish mail...and therefore does not send it. but why???

I expect it to send mail but it does not


Solution

  • This is probably a difference in the version of telnet, not the version of bash.

    One common problem when using network tools in a pipeline like this is how they handle EOFs on stdin. What you need is behavior like this:

    • Your input is written to telnet's stdin
    • ...while this is happening, telnet starts sending that input to the remote server...
    • Telnet's stdin is given an EOF (end-of-file). Some broken versions of telnet exit immediately at this point.
    • ...telnet keeps sending everything it read from its stdin over to the remote server.
    • ...telnet finishes sending everything it read to the remote server, and then closes the sending side of the socket (via a FIN packet)
    • ...the server keeps sending content to the client until it's sent any responses that need to be done, and then the server closes its own side by sending another FIN
    • telnet prints everything it got prior to getting a FIN from the server. Completion of this step is when a correctly-written telnet actually exits.

    As noted above, many versions of telnet that actually exist were written assuming they would be used by humans, not scripts. Instead of sending buffered content over the wire on receiving an EOF, and waiting to receive any responses from the server before shutting down the receive side, they just quit immediately the moment an EOF is seen.


    You can work around it by adding a delay at the end.

    It's an ugly hack, and better replaced with using tools that know how to shut down a socket correctly, but the cheap-and-dirty approach looks something like this:

    { ...; echo "."; echo "quit"; sleep 2; } | telnet mailserver.actualdomain.org 25
    

    For new development, consider using a built-to-purpose tool like socat, or one of the many implementations of netcat.

    socat's documented behavior explicitly makes it wait to finish sending content it received on its stdin, and printing responses it received over the socket, before exiting; insofar as it has a timeout on how long it waits for responses from the server, that timeout can be explicitly configured.