TCPSocket and RFC 821

S

Satish Talim

I wanted to send an email from my desktop using a simple Ruby program.
I installed 1st SMTP Server
(http://www.emailarms.com/products/1st_smtp.html) - an easy to use
SMTP mail relay server. It is used for relaying your email messages to
its destinations quickly and easily. For this server, I need to use
localhost and port 25 on my PC.

Then the program I wrote was (based on RFC 821) -

require 'socket'
t = TCPSocket.new('localhost', 25)
puts t.gets
t.puts 'HELO Welcome from Ruby'
puts t.gets
t.puts 'MAIL FROM:<[email protected]>'
puts t.gets
t.puts 'RCPT TO:<[email protected]>'
puts t.gets
t.puts 'DATA'
puts t.gets
t.puts 'Test Email from Ruby'
t.puts "\r\n.\r\n"
puts t.gets
t.puts 'QUIT'
puts t.gets
t.close

However, while running the program, I get an error as follows:

220 Welcome to the 1st SMTP Server

250 Hello Welcome from Ruby

250 (e-mail address removed) Address Okay

250 (e-mail address removed) Address Okay

354 Start mail input; end with <CRLF>.<CRLF>

nil
email.rb:15:in `write': Invalid argument (Errno::EINVAL)
from email.rb:15:in `puts'
from email.rb:15
Exit code: 1

I am unable to figure out what the problem is. All help appreciated.
 
F

Francis Cianfrocca

This line:
t.puts "\r\n.\r\n"
puts one more linefeed on the output than you perhaps intended, which
may account for the nil in your output. The QUIT command may be
causing the localhost server-connection to close before your process
has a chance to read the input. Meaning that the EINVAL error is
generated by the gets call you make right after sending QUIT.

Try the same program with a mail server located on a different machine
and see if you get a different result. After sending QUIT on an SMTP
connection, you don't really need to read the server response. (Unless
you suspect for some reason the server will send an interesting
error-response to your QUIT, which I've never seen in many years of
working with SMTP servers.)
 
Y

Yohanes Santoso

Satish Talim said:
I wanted to send an email from my desktop using a simple Ruby program.
I installed 1st SMTP Server
(http://www.emailarms.com/products/1st_smtp.html) - an easy to use
SMTP mail relay server. It is used for relaying your email messages to
its destinations quickly and easily. For this server, I need to use
localhost and port 25 on my PC.

Then the program I wrote was (based on RFC 821) -

require 'socket'
t = TCPSocket.new('localhost', 25)
puts t.gets
t.puts 'HELO Welcome from Ruby'
puts t.gets
t.puts 'MAIL FROM:<[email protected]>'
puts t.gets
t.puts 'RCPT TO:<[email protected]>'
puts t.gets
t.puts 'DATA'
puts t.gets
t.puts 'Test Email from Ruby'
t.puts "test email from ruby\r\n"
 
F

Francis Cianfrocca

Satish said:
t.puts 'DATA'
puts t.gets
t.puts 'Test Email from Ruby'
t.puts "\r\n.\r\n"

Ok, so obviously you're not sending a normal RFC-822 header here. Is it
possible that your SMTP server is so strict about this that it closes
the connection silently?
 
Y

Yohanes Santoso

Satish Talim said:
I tried the various suggestions given by Francis and Yohanes, but still it
does not work.

The executable code now is:

require 'socket'
t = TCPSocket.new('localhost', 25)
puts t.gets
t.puts "HELO Welcome from Ruby\r\n"
puts t.gets
t.puts "MAIL FROM:<[email protected]>\r\n"
puts t.gets
t.puts "RCPT TO:<[email protected]>\r\n"
puts t.gets
t.puts 'DATA'
puts t.gets
t.puts "Test email from ruby\r\n"
t.puts "\r\n.\r\n"
t.puts 'QUIT'
puts t.gets
t.close

and the output is:

220 Welcome to the 1st SMTP Server

250 Hello Welcome from Ruby

250 (e-mail address removed) Address Okay

250 (e-mail address removed) Address Okay

354 Start mail input; end with <CRLF>.<CRLF>

nil

/tmp $ ruby try.rb
220 jenny-gnome.dyndns.org ESMTP
250 jenny-gnome.dyndns.org
250 ok
250 ok
354 go ahead
250 ok 1154319423 qp 25461
/tmp $

What is your SMTP server?
I'd appreciate any other suggestions. Incidentally, if I write a program
using the Net::SMTP class, I am able to send off emails with my current
configuration.

Please paste this code that uses Net::SMTP.

YS.
 
F

Francis Cianfrocca

Satish said:
I tried the various suggestions given by Francis and Yohanes, but still
it
does not work.

What happens if you simply telnet to the SMTP server and enter all of
the commands interactively? And, based on your last code framgment, you
haven't cleaned up all the extra linefeeds you're sending. Change puts
to write throughout, and change "QUIT" to "QUIT\r\n"

Also, your Net::SMTP fragment uses authentication and your socket-code
fragment does not. Although most mail servers would give a recognizable
error msg if they required auth.
 
F

Francis Cianfrocca

Satish said:
I used Telnet and it got stuck when I typed . to stop the DATA. What
change
do I need to make in the TCPSocket code for authentication?

What does "got stuck" mean? Did it give an error message? Did it close
the connection? Did it hang? Show us a screenshot of the telnet
conversation.
 
F

Francis Cianfrocca

Satish said:
Here's my Telnet session using 1st SMTP server.

----------------------------------
220 Welcome to the 1st SMTP Server
HELO
250 Hello
MAIL FROM:<[email protected]>
250 (e-mail address removed) Address Okay
RCPT TO:<[email protected]>
250 (e-mail address removed) Address Okay
DATA
354 Start mail input; end with <CRLF>.<CRLF>
This is the Telnet transcript
For Ruby Talk
.

Try this instead:
-------------------------
DATA
354 Start.....
Subject: This is an email

This is the telnet transcript
 
F

Francis Cianfrocca

Satish said:
Francis, thanks for helping me along. I tried your suggestions. However,
it
still does not work. Do you know the ESMTP command sequence to send an
email
over TSL and Authenticate?

Well, maybe try something like this:
Use EHLO instead of HELO.
After EHLO and before MAIL FROM, send:

AUTH PLAIN xxx\r\n

where xxx is the base-64 encoding of a string consisting of a binary
zero followed by your account name (on the mail server), followed by
another binary zero, followed by your password. In Ruby, perhaps
something like

require 'base64'
Base64.encode64( "\000#{username}\000#{psw}" ).chomp
 
Y

Yohanes Santoso

Satish Talim said:
Like I said before I am using a relay SMTP server called 1st SMTP server on
my Windows XP. The code using TCPSocket does not do authenticate and as such
I am not using our actual SMTP server.


Could it be that the SMTP server (relay or not), does a running
verification for the content of the data?

That is, if the data is not in RFC822 format, then it aborts the
connection ungracefully.

Or, could it be aborting the connection because you don't authenticate
when using the TCPSocket version?

YS.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top