Ruby: DATA SMTP Client Class

Closed - This job posting has been filled and work has been completed.

Job Description

Your Task:

To Create a SMTP Client Class in Ruby based on TCP Sockets and no other libraries.
No Eventmachine!

Description:

I'm calling your SMTP Client Class like this:

status = SmtpClient.send(data)

The Variable "data" is this Hash:
data = {
"verbose" => false,
"connection" => {
"connection_timeout" => 5,
"response_timeout" => 3,
"host" => "mta5.am0.yahoodns.net", # Yahoo's Mail Server. I DON'T need DNS-Resolving here as I will specify the server myself directly
"port" => 25,
"reverse_dns" => "mydomain.com", # Used in the EHLO message
"bind_ip" => "127.0.0.1", # Local IP to bind
},
"emails" => [
{
"from_email" => "my_from@my_domain.com";, # For SMTP Dialog
"recipients" => [ "external1@hotmail.com";, "external2@hotmail.com";, ... ],
"message" => "To: \"Foo\" <bar@foo.com>\nSubject: Foo Bar\n\nThis is the message!",
},
{
"from_email" => "my_from@my_domain.com";, # For SMTP Dialog
"recipients" => [ "external1@hotmail.com";, "external2@hotmail.com";, ... ],
"message" => "To: \"Foo\" <bar@foo.com>\nSubject: Foo Bar\n\nThis is the message!",
},
{
"from_email" => "my_from@my_domain.com";, # For SMTP Dialog
"recipients" => [ "external1@hotmail.com";, "external2@hotmail.com";, ... ],
"message" => "To: \"Foo\" <bar@foo.com>\nSubject: Foo Bar\n\nThis is the message!",
},
.... # other messages here eventually
]
}

Your SMTP Client will connect to a remote mail server via TCP Socket according to data["connection"].
Every email in the data["emails"] Array is then sent out.

RETURN VALUES:
Your client returns an Array of the Recipients that were or weren't sent successfully.
There are various outcomes:
1.) All messages delivered successfully
return ==> { "success" => [ "email1@yahoo.com";, "email2@yahoo.com",... ] }
2.) Some messages were not delivered since all recipients of the respective message bounced
(RCPT TO: <email@foo.com>; might return an Error from the SMTP server when this email account is not existing)
return ==> { "success" => [...], "bounces" => [...] }
3.) There migth be various SMTP errors or Connection errors.
Examples:
- Connection could not be established since the host does not respond
(You should implement a timeout according to data["connection"]["connection_timeout"])
return ==> { "error" => "Timeout - Host did not respond" }
- Or, during the SMTP Dialog the remote server sends an error like "421, Sending Limit reached for this IP"
Such errors appear mostly after "MAIL FROM" or after the DATA was sent.
return ==> { "error" => "550 [TS01] Messages were not sent", "command" => "MAIL FROM" }
# this should contain the actual error message from the SMTP server, plus a "command" => "..."
# field that says what command was sent when the error appeared


MISC:
This will be part of a commercial MTA (Newsletter & Notification System).
Your code will be running in a Thread (since there will be simulteanous connections).
Please make sure that there are no restrictions from your side regarding Threading.
(For example I saw TCP messages getting mixed up when dealing with multiple TCP connections)

Other open jobs by this client