PDA

View Full Version : Sending mail - problem with authentication



kremuwa
9th March 2010, 11:15
Hello. I wanted to add an option to my application, which lets user to send e-mail to my mailbox (my mail adress is set in the source code). I found the source code for this feature on the net and everything is quite good until... the SMTP server is sending me responses like: "Server XYZ requires Authentication .... blah blah". As SMTP server I'm using popular mail services' servers and they obviously requires Authentication. What does it mean? How to do the Authentication? I tried to look for servers withoud this need but the results were terrible - I haven't found anything. I can't use localhost, because it won't work for other users (who don't have servers installed).

Help me, please :). Thanks in advance.

toutarrive
9th March 2010, 12:07
It looks like that you have to provide a username and a password before being able to use the SMTP protocol.

kremuwa
9th March 2010, 12:32
Ok, so here is the code (it comes from this forum).

smtp.h:

#ifndef SMTP_H
#define SMTP_H

#include <QApplication>
#include <QMessageBox>
#include <QtDebug>
#include <QString>
#include <QObject>
#include <QTcpSocket>
#include <QTextStream>

class Smtp : public QObject
{
Q_OBJECT

public:
Smtp( const QString &from, const QString &to, const QString
&subject, const QString &body );
~Smtp();

signals:
void status( const QString & );

private slots:
void readyRead();
void connected();

void stateChanged( QAbstractSocket::SocketState socketState );
void errorReceived( QAbstractSocket::SocketError socketError );
void disconnected();

private:
enum State {
Init,
Mail,
Rcpt,
Data,
Body,
Quit,
Close
};

QString message;
QString from;
QString rcpt;
QTcpSocket * socket;
QTextStream * t;
int state;
QString response;
};

#endif // SMTP_H

smtp.cpp:

#include "smtp.h"

Smtp::Smtp( const QString &from, const QString &to, const QString
&subject, const QString &body )
{
socket = new QTcpSocket( this );
connect( socket, SIGNAL( readyRead() ), this, SLOT( readyRead() ) );
connect( socket, SIGNAL( connected() ), this, SLOT( connected() ) );
connect( socket, SIGNAL( error( QAbstractSocket::SocketError) ),
this, SLOT( errorReceived( QAbstractSocket::SocketError ) ) );
connect( socket, SIGNAL( stateChanged( QAbstractSocket::SocketState)
), this, SLOT( stateChanged( QAbstractSocket::SocketState ) ) );
connect( socket, SIGNAL( disconnectedFromHost()), this,
SLOT(disconnected() ) );
message = QString::fromLatin1( "From: " ) +from
+QString::fromLatin1( "\nTo: " ) +to +QString::fromLatin1( "\nSubject: "
) +subject +QString::fromLatin1( "\n\n" ) +body +"\n";
message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1(
"\r\n" ) );
message.replace( QString::fromLatin1( "\r\n.\r\n" ),
QString::fromLatin1( "\r\n..\r\n" ) );
this->from = from;
rcpt = to;
state = Init;

// change this to correct email server address
socket->connectToHost( "smtp.poczta.onet.pl", 25 );

if( socket->waitForConnected( 5000 ) )
qDebug("connected");

t = new QTextStream( socket );
}

Smtp::~Smtp()
{
delete t;
delete socket;
}
void Smtp::stateChanged( QAbstractSocket::SocketState socketState)
{
qDebug() <<"stateChanged " << socketState;
}

void Smtp::errorReceived( QAbstractSocket::SocketError socketError)
{
qDebug() << "error " <<socketError;
}

void Smtp::disconnected()
{
qDebug() <<"disconneted";
qDebug() << "error " << socket->errorString();
}

void Smtp::connected()
{
qDebug() << "Connected ";
}

void Smtp::readyRead()
{
if( !socket->canReadLine() )
return;

QString responseLine;

do {
responseLine = socket->readLine();
response += responseLine;
} while( socket->canReadLine() && responseLine[3] != ' ' );

responseLine.truncate( 3 );

if ( state == Init && responseLine[0] == '2' )
{
// banner was okay, let's go on
*t << "HELO there\r\n";
t->flush();
state = Mail;
}
else if ( state == Mail && responseLine[0] == '2' )
{
// HELLO response was okay (well, it has to be)
*t << "MAIL FROM: <" << from << ">\r\n";
t->flush();
state = Rcpt;
}
else if ( state == Rcpt && responseLine[0] == '2' )
{

*t << "RCPT TO: <" << rcpt << ">\r\n";
t->flush();
state = Data;
}
else if ( state == Data && responseLine[0] == '2' )
{
*t << "DATA\r\n";
t->flush();
state = Body;
}
else if ( state == Body && responseLine[0] == '3' )
{
*t << message << ".\r\n";
t->flush();
state = Quit;
}
else if ( state == Quit && responseLine[0] == '2' )
{
*t << "QUIT\r\n";
// here, we just close.
state = Close;
//t->flush();
emit status( tr( "Message sent" ) );
}
else if ( state == Close )
{
deleteLater();
return;
}
else
{
// something broke.
QMessageBox::warning( qApp->activeWindow(), tr( "Qt Mail Example" ), tr( "Unexpected reply from SMTP server:\n\n" ) + response );
state = Close;
}
response = "";
}


The way I'm using it:

Smtp *newMail = new Smtp("anonymous@gall.com","recipient@mail.com","Such a title","Such mail content");

What should I change to make it work?

toutarrive
9th March 2010, 13:07
You still have to provide authentification if the SMTP requires one.

wysota
9th March 2010, 14:12
What should I change to make it work?
Do you expect us to do your work for you?

And to formally answer your question - "change your approach from expecting others to do your work for you and copying their code to doing something on your own". You can start with understanding how the SMTP protocol works. If you still want to copy code, find a more complete solution to copy from - I know there are a few of those as I have written (and published) one myself.

kremuwa
9th March 2010, 14:53
Ok, I managed to do it by myself. Sorry for my ignorance

toutarrive
9th March 2010, 16:11
It has got nothing to do with 'ignorance' (we went all trought it, and knowledge is never achieved anyway) but rather that people are willing to help you but not code for you .

kremuwa
9th March 2010, 18:28
I see... So... will you help me with setting a right text codec for the mail? I'm using polish letters - ś, ć, ź, ą, ń, ó, ę. They are not correctly shown in the message (I can see something like ¹æêñóœŸ). I don't know how to deal with it.

squidge
9th March 2010, 18:48
I think your going about it completely the wrong way. If there's a mail server around that will accept mail without authentication, spammers will quickly find it and use it to send millions of emails per day through. So you need a username and password, and hardcoding ones that work into your application would be silly as those details would be quickly abused by others.

So you have two options: You can setup a server somewhere (non-SMTP or only accepts email to one particular address and on a non-standard port) and have your program connect to that, or you can use the users own mail client. Most individuals use the later. Organisations (such as Mozilla) typically use the former.

If you wish to use non-ascii characters in an email (such as polish letters), then you need to learn about MIME content transfer encoding. I remember it being discussed in RFC 2045.

wysota
9th March 2010, 19:05
Also let's not forget that the mail server is not interpreting the contents of the message in any way (everything between "data" and "." is just passed through), it's just the client applications that do. Bottom line is you just need to format your content properly.

kremuwa
10th March 2010, 08:46
Thanks for both of you.

fatjuicymole - currently I'm connecting to smtp server (which belongs to poczta.onet.pl - popular mail service in poland) using my login and password which are specified in the code. Are you saying that "bad people" will fetch this data? What can they do then?

If I create my own SMTP server, which would accept mails from only one mail adress on non-standard port, as you said - amm... will it cost much money?

squidge
10th March 2010, 13:50
"bad people" can use your login and password to send thousands of emails to people. This can happen until your account is banned.

If you create your own SMTP server, it will be free of charge if you host it yourself on your own connection, else you need to shop around. It can be expensive.

kremuwa
10th March 2010, 14:35
If I host my own SMTP server, can't they use it knowing my login data (fetched from my program)? And how can I accept mails only from one specified e-mail adress? Is this a kind of property of an SMTP server?

toutarrive
10th March 2010, 14:37
currently I'm connecting to smtp server (which belongs to poczta.onet.pl - popular mail service in poland) using my login and password which are specified in the code. Are you saying that "bad people" will fetch this data? What can they do then?

Harcoding your login and password make yourself recognize by the server (so validate the connection). And then, people using your app will be seen by the server as if you were the one sending a mail.

Instead your app should asked for a valid login and password on the relevant SMTP server. So, never harcode one in your app.

squidge
10th March 2010, 17:28
If you hosted your own SMTP server, it would be impractical for other people to use it, as it would only ever accept mail to local addresses to itself (where there might only be one), so other people just wouldn't bother.

Spammers are only interested in "open" mail servers - those which will accept mail destined for anywhere. As soon as your mail server rejects all non-local mail, people lose interest very quickly and go find some other mail server. This is the typical mail server configuration.

wysota
10th March 2010, 18:17
I think bringing up your own mail server is an overkill here. A solution with the end-user providing authentication data to the application is much better. A not so bad alternative is to embed some of the capabilities of an smtp server directly into your application. Actually what is required besides what the client side of smtp offers is an ability to query dns for an MX record for a particular destination address. When you connect to the appropriate server, it won't require you to authenticate yourself (i.e. you don't need to authorize to poczta.onet.pl if you are sending mails destined for poczta.onet.pl domain). Unfortunately QHostInfo doesn't provide means for querying for MX records so this needs to be done manually.

kremuwa
10th March 2010, 21:31
toutarrive, wysota - I'm not sure if I got you well but let me explain what do I need it for. I've got pretty small application, which I want to have one additional feature - it should send mails to my mail account, containing information about bugs and opinions from users. They click "send mail" in menu, they write a message content, they specify their e-mail (so I can answer them) and they click "Send". I only want this mail to be delivered to my e-mail account - nothing else. So asking user for login and password is not a good solution here. Now, with such a knowledge, could you say what would be the best thing to do here?

toutarrive
10th March 2010, 22:06
See answers #9 and #16.

squidge
10th March 2010, 22:38
toutarrive, wysota - I'm not sure if I got you well but let me explain what do I need it for. I've got pretty small application, which I want to have one additional feature - it should send mails to my mail account, containing information about bugs and opinions from users. They click "send mail" in menu, they write a message content, they specify their e-mail (so I can answer them) and they click "Send". I only want this mail to be delivered to my e-mail account - nothing else. So asking user for login and password is not a good solution here. Now, with such a knowledge, could you say what would be the best thing to do here?

The best thing to do would be to fire up the users email client, let them write the message content there, and then click send. No need to request there email address, as the email client will have that already. It'll also go through the appropriate mail server so you don't need to worry about that.

Why make it more complicated than it needs to be?

wysota
10th March 2010, 23:46
toutarrive, wysota - I'm not sure if I got you well but let me explain what do I need it for. I've got pretty small application, which I want to have one additional feature - it should send mails to my mail account, containing information about bugs and opinions from users. They click "send mail" in menu, they write a message content, they specify their e-mail (so I can answer them) and they click "Send". I only want this mail to be delivered to my e-mail account - nothing else. So asking user for login and password is not a good solution here. Now, with such a knowledge, could you say what would be the best thing to do here?

If you are going to send mail to only one specific address (yours) then you can hardcode your application to connect directly to the server handling mail for your account and transmit the message directly to it withouth authenticating. Just be aware that should the mx record for the domain be changed, your application will not be able to transmit emails anymore.

A much cleaner approach would be to have a php script somewhere in the web that would receive feedback from your application instead of using smtp protocol and emails for this. Getting free hosting with php capabilities shouldn't pose any problem.