SFML community forums

Help => Network => Topic started by: KingPenguinator on June 18, 2014, 06:42:29 pm

Title: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 06:42:29 pm
Hi, is it possible to use the network module in SFML to send an e-mail ?

Like "Hi, blalalalalalla" to example@something.com
Title: Re: Sending string to an e-mail adress
Post by: Jesper Juhl on June 18, 2014, 06:50:57 pm
Not easily.

But you can of course
 - open a TCP socket to port 25 of your mail server.
 - send the proper ESMTP commands to describe the mail source and destination.
 - send the body of the mail.
 - send the proper command to say goodbye to the mail server once it has acknowledged that the mail has been sent.
 - close the TCP socket.

Just like a real mail client would do.


 
Relevant reading material:
 http://en.m.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
 http://en.wikipedia.org/wiki/Extended_SMTP
 http://tools.ietf.org/html/rfc5321
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 06:58:04 pm
Ok, i'll see what I can do ^^
Thx
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 09:31:44 pm
Done this so far:

#include "iostream"
#include "SFML/Network.hpp"

using namespace std;

int main()
{
    sf::IpAddress ip("smtp.live.com");
    sf::TcpSocket socket;

    if(socket.connect(ip, 587)==sf::Socket::Done)
    {
        cout << "yay" << endl;
    }
    else
        cout << "crap" << endl;

    sf::Packet packet;
    packet << "HELO keylog";
    socket.send(packet);

    packet << "MAIL FROM: blank@example.com";
    socket.send(packet);

    packet << "RCPT TO: me@live.com";
    socket.send(packet);

    packet << "DATA";
    socket.send(packet);

    packet << "Message";
    socket.send(packet);

    packet << ".";
    socket.send(packet);

    packet << "QUIT";
    socket.send(packet);

    return 0;
}

 

Not receiving anything, am I forgetting anyting ?
Title: Re: Sending string to an e-mail adress
Post by: Ixrec on June 18, 2014, 09:50:32 pm
Are you listening for a response?
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 09:52:34 pm
I should receive an e-mail from the program no ?
Title: Re: Sending string to an e-mail adress
Post by: Laurent on June 18, 2014, 10:04:40 pm
You never clear your packet between two consecutive send, data is accumulating in the packet.

And I don't know the SMTP protocol, but you should probably get a response for each command that you send.
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 10:11:17 pm
You never clear your packet between two consecutive send, data is accumulating in the packet.

Wasn't sure about that, but i've tried clearing with :
string aux;
packet << "HELO keylog";
socket.send(packet)
packet >> aux;
 

That should clear it right ?
Title: Re: Sending string to an e-mail adress
Post by: Ixrec on June 18, 2014, 10:13:27 pm
It's probably safer (and more readable) to use packet.clear().
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 10:25:55 pm
Ok, so i'm using packet.clear() between each socket.send(), still not working, I believe the problem is coming from the way i'm sending my messages, I get the feeling they're not right with the SMTP, anyone with any experience with SMTP and C++ could probably see what's up.
Title: Re: Sending string to an e-mail adress
Post by: Jesper Juhl on June 18, 2014, 10:32:00 pm
Try it out by hand first with a tool such as "nc" (netcat) or "telnet".

For example, here's me holding a little conversation with my own mail server (the lines that start with a number are messages from the mailserver, the other lines are from me):

Code: [Select]
[jj@firebreather ~]$ nc swampdragon.chaosbits.net 25
220 swampdragon.chaosbits.net ESMTP 8BIT-OK NO UCE NO UBE Postfix
EHLO firebreather.chaosbits.net
250-swampdragon.chaosbits.net
250-PIPELINING
250-SIZE 60000000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:<jj@chaosbits.net>
250 2.1.0 Ok
RCPT TO:<postmaster@chaosbits.net>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: "Jesper Juhl" <jj@chaosbits.net>
To: Postmaster <postmaster@chaosbits.net>
Date: Wed, 18 June 2014 22:27:00 +0100
Subject: A test mail

Hello Postmaster. Hope you are well.   

Greetings from Jesper

.
250 2.0.0 Ok: queued as DB54F9403B
QUIT
221 2.0.0 Bye
[jj@firebreather ~]$

Remember that you must read the messages from the mail server as well as sending your own stuff and the mailserver initiates the conversation so you must start out by reading its greeting message.
Also remember that your lines must end with carriage-return + linefeed (that is "\r\n") or the mail server will see everything you send as one long garbage command.
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 18, 2014, 11:00:43 pm
Thx jespere for the tip, i'll have a look at that tomorrow =)
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 19, 2014, 12:52:37 pm
Ok, so i've modified it a bit, i'm not using packets anymore, and i'm now listening for responses:

#include "iostream"
#include "SFML/Network.hpp"

using namespace std;

int main()
{
    sf::IpAddress ip("smtp.live.com");
    sf::TcpSocket socket;

    if(socket.connect(ip, 587)==sf::Socket::Done)
    {
        cout << "yay" << endl;
    }
    else
        cout << "crap" << endl;

    char helo[100] = "HELO server\r\n";
    socket.send(helo, 100);

    char data[1000];
    size_t received;
    if(socket.receive(data, 1000, received) == sf::Socket::Done)
    {
        cout << data << endl;
    }

    char mailFrom[100] = "MAIL FROM: someone@something.com\r\n";
    socket.send(mailFrom, 100);

    char mailD[1000];
    size_t mailR;
    if(socket.receive(mailD, 1000, mailR) == sf::Socket::Done)
    {
        cout << mailD << endl;
    }

    char rcptTo[100] = "RCPT TO: me@live.com\r\n";
    socket.send(rcptTo, 100);

    char dataC[100] = "DATA\r\n";
    socket.send(dataC, 100);

    char msg[100] = "Message blabablabla\r\n";
    socket.send(msg, 100);

    char endC[100] = "\r\n.\r\n";
    socket.send(endC, 100);

    char dataD[1000]; // I've placed a response listener after every message send, I only get a reponse when I put it here, and not sooner.
    size_t dataR;
    if(socket.receive(dataD, 1000, dataR) == sf::Socket::Done)
    {
        cout << dataD << endl;
    }

    char quit[100] = "QUIT\r\n";
    socket.send(quit, 100);

    return 0;
}

 

Not very clean, but I get a response :
220 BLU436-SMTP168.smtp.hotmail.com Microsoft ESMTP MAIL Service, Version: 8.0.9
200.16384 ready at  Thu, 19 Jun 2014 03:43:19 -0700
o
250 BLU436-SMTP168.smtp.hotmail.com Hello [xxx.xx.xxx.xxx] // This is my ip, I hid it
∟☺
530 5.7.0 Must issue a STARTTLS command first

The problem now is that last line, I don't know how to issue a STARTTLS command, i've tried sending STARTTLS to the server at each possible position, still get this message.
Title: Re: Sending string to an e-mail adress
Post by: Jesper Juhl on June 19, 2014, 01:57:08 pm
STARTTLS is for initiating an encrypted session.
See if you can talk to the server on port 25 instead, without encryption.
Title: Re: Sending string to an e-mail adress
Post by: KingPenguinator on June 19, 2014, 02:12:51 pm
STARTTLS is for initiating an encrypted session.
See if you can talk to the server on port 25 instead, without encryption.

I tried it, doesn't work, I get the same message, maybe I have to specify I don't want to use it ?
Title: Re: Sending string to an e-mail adress
Post by: Jesper Juhl on June 20, 2014, 06:07:26 pm
If the server insists on using encryption there's really no way around that.

As I see it, you have a few options:

1. Find a different mail server to relay your messages through that does not require TLS.

2. Use OpenSSL, GNUTls or another similar library to add encryption capabilities to your application so you can talk to your current mail server.

3. Set up your own mail server with Postfix, Sendmail or similar and then relay messages via that.

4. Use an existing commandline mail program like mailx to send your messages and invoke it from your program via system() or similar.

But anyway, this no longer has much (anything) to do with SFML...