Seite 1 von 1

[GELÖST] emails mit qt4 aus dem code heraus versenden

Verfasst: 14. November 2007 14:33
von peter999
Hallo,
weiss zufällig jemand, wie man emails aus einer qt-basierenden Anwendung senden kann ? Ist das direkt mit QT4-Code möglich oder ist dann wieder eine "betriebsystem-" API notwendig ?

Gruß Peter
qt 4.3.2 commercial, VS 2005 Prof, XP Pro SP2

Verfasst: 14. November 2007 15:02
von macman
Welches Protokoll? SMTP? Du machst einen Socket zum SMTP-Server auf und verschickst ein paar Nachrichten. Etwas mehr -> SMTP-Protokoll
IMAP dürfte schwieriger werden, kenne ich zwar, nutze es aber nicht.

Verfasst: 15. November 2007 09:31
von peter999
@macman
Danke für die Info, es geht einfach um SMTP, um aus dem Programm Nachrichten versenden zu können.
Die Wikipedia Seite habe ich auch gelesen, mit telnet server 25 kriege ich es auch hin. Aber die Klasse, die ich gebastelt habe, klappt irgendwie nicht, denn ich bekomme zwar mit Telnet die "220 xxx server ready", aber über QTcpSockets kommt als Antwort immer 0 Byte...

Ich habe das Beispiel für den Fortune Client als Vorlage genommen, Verbindung bekomme ich, das Signal readyRead kommt auch, aber ich bekomme nur 0 Bytes....

Hier mal meine "Bastelklasse": (Windows XP, VS 2005 Prof, QT 4.3.2 Kommerziell)
cpp:

#include "pbsmtp.h"
#include <QtCore>

PBSmtp::PBSmtp(QObject *parent)
: QObject(parent)
{
SMTP_Server = "localhost";
SMTP_Port = 25;
tcpSocket = 0;
}

PBSmtp::~PBSmtp()
{
if (tcpSocket)
delete tcpSocket;
}

int PBSmtp::startSMTP(QString host, unsigned int port)
{
QByteArray array;
if (tcpSocket)
{
delete tcpSocket;
tcpSocket = 0;
}
if (!tcpSocket)
tcpSocket = new QTcpSocket(this);
if (!tcpSocket)
return -1;
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readSMTP()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
tcpSocket->abort();
tcpSocket->setReadBufferSize(60000);
tcpSocket->connectToHost(host, port, QIODevice::ReadWrite);
if (tcpSocket->waitForConnected(10000) == false) // Warte, bis wir verbunden sind
{
emit sendMessage(tr("SMTP: Keine Verbindung zum Mailserver"));
return -2;
}
// das habe ich eingebaut, um mal zu sehen, ob ich was senden muss, dass der Server reagiert
char buffer[2] = { 0xd, 0};
tcpSocket->write(&buffer[0]);

if (tcpSocket->waitForReadyRead() == false)
{
emit sendMessage(tr("SMTP: Mail Server reagiert nicht auf Anforderung"));
return -2;
}
else
emit sendMessage(tr("SMPT: Mail Server bereit"));
// da habe ich getestet, ob noch was nachkommt...
array = tcpSocket->read(500);
return 0;
}

int PBSmtp::endSMTP()
{
if (tcpSocket)
{
delete tcpSocket;
tcpSocket = 0;
}
return 0;
}

int PBSmtp::sendMail(QString from, QString to, QString subject, QString Text)
{
return 0;
}

// SLOTS
void PBSmtp::readSMTP()
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_0);
in >> ComLine;
qDebug() << "readSMTP Anzahl Bytes = " << tcpSocket->bytesAvailable() << " String = " << ComLine;
}

void PBSmtp::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
emit sendMessage(tr("SMTP: Der E-Mail server wurde nicht gefunden, bitte prüfen Sie den Host-Namen und den Port."));
break;
case QAbstractSocket::ConnectionRefusedError:
emit sendMessage(tr("SMTP: Die Verbindung wurde durch den Server verweigert. Stellen Sie sicher, dass der E-Mail Server aktiv ist und prüfen Sie die Einstellungen."));
break;
default:
emit sendMessage(tr("SMTP: Folgender Fehler trat auf: %1.").arg(tcpSocket->errorString()));
break;
}
}

hpp:

#ifndef PBSMTP_H
#define PBSMTP_H

#include "dakydlldefs.hpp"
#include <QObject>
#include <QTcpSocket>


class PB_DLLEXPORT PBSmtp : public QObject
{
Q_OBJECT

public:
PBSmtp(QObject *parent);
~PBSmtp();
int startSMTP(QString, unsigned int);
int endSMTP();
int sendMail(QString from, QString to, QString subject, QString Text);

private:
QTcpSocket *tcpSocket;
QString SMTP_Server;
unsigned int SMTP_Port;
QString ComLine;

private slots:;
void readSMTP();
void displayError(QAbstractSocket::SocketError socketError);

signals:;
void sendMessage(QString);
};

#endif // PBSMTP_H


Aufruf mit (Eingaben sind natürlich bei mir richtig angegeben, der Janaserver läuft auf einem anderen PC und man kann mit Telnet verbindung aufnehmen und senden).

PBSmtp Smtp(this);
Smtp->startSMTP("localhost", 25);
Smtp->sendMail("x.y@murks.com","mich@domain.de", "Testmail", "Testmailtext");
Smtp->endSMTP();

Für jede Idee bin ich dankbar

Gruß Peter

Verfasst: 15. November 2007 10:00
von peter999
@macman

Hat sich mittlerweise erledigt, ich habe den Slot jetzt so geschrieben:
void PBSmtp::readSMTP()
{
qint64 anzahl = tcpSocket->bytesAvailable();
QByteArray array = tcpSocket->readAll();
ComLine = array;
qDebug() << "readSMTP Anzahl Bytes = " << anzahl << " String = " << ComLine;
}

Damit meldet sich der Server treu und brav....

Trotzdem Danke.

Gruß aus Franken
Peter

Verfasst: 15. November 2007 10:03
von macman
Benutze bitte die Code-Tags, so ist das besch... eiden zu lesen.

Wenn der Server auf einem anderen PC läuft, warum dann localhost? Ich habe jetzt nicht die Zeit das alles zu testen, aber ich würde sowas wie Wireshark nehmen, um den Netzwerktraffic zu kontrollieren.

Verfasst: 15. November 2007 11:55
von peter999
@macman

Was sind Code-Tags ?

nun zur Frage, wenn ich "Demo Code" in der Mail anzeige, dann ja wohl nicht mit realen Adressen, sonst habe ich in kürzester Zeit ein Spam Relais....

Gruß Peter

Verfasst: 15. November 2007 12:18
von macman
peter999 hat geschrieben:Was sind Code-Tags ?
Hast Du dir die anderen Postings hier schon mal angesehen? Da erscheinen immer wieder mal Boxen wie:

Code: Alles auswählen

Beispielcode
Sorgen eigentlich nur dafür das eine Formatierung erhalten bleibt.
Wenn Du eine Nachricht schreibst, dann siehst Du über dem Editfeld ein paar Buttons, einer lautet 'Code'.
peter999 hat geschrieben:nun zur Frage, wenn ich "Demo Code" in der Mail anzeige, dann ja wohl nicht mit realen Adressen, sonst habe ich in kürzester Zeit ein Spam Relais....
Dann nimm Konstanten oder Variablen, würde man im Code doch auch so machen.

funktioniert nicht !

Verfasst: 30. Dezember 2007 02:00
von nvdstruis
Hallo Leute,

Ich habe Peter's smtp Beispiel versucht, aber es funktioniert nicht. Nach dem "server bereit" Bericht ist nichts mehr ! Ich habe es versucht mit einem richtigen smtp Server und mit meinem eigenen "user" und "password".

Funktioniert es bei euch ?

Ich bin sehr interessiert. Gruss,

Nils

Verfasst: 30. Dezember 2007 10:12
von patrik08
Ein jahr lang habe ich smtp auth gebraucht..
mein beispiel code:
svn co
https://qt-webdav.svn.sourceforge.net/s ... h_console/
mail

Aber es ist nicht elegant user und pass + server in einen programm zu haben und verteilen, auch fuer update, darum benutze ich mittlerweile die technologie pdf formulare
pdf - fdf ... && xfdf.

mit xdf oder fdf kann man die daten des formular auffuellen aus von dbs utf-8 dann muss man nur das formular aus der resource rausholen und im gleichen ordner des xfdf - fdf abspeichern .. als letzt das xfdf oder fdf aufrufen mit


Code: Alles auswählen

void OpenDesktop( QUrl loc )
{
    #if defined Q_WS_MAC
    QProcess *m = new QProcess();
    QStringList macs;
    macs << loc.toString();  /* oeffnet der default browser */
    m->startDetached(QString("open") , macs );
    ///////std::cout << "OpenDesktop [" << qPrintable(macs.join(" ")) << "]" << std::endl;
    return;
    #endif 
    
#if defined Q_WS_WIN
    
    QString fullFileName = loc.toString();
    
    if (fullFileName.startsWith("http://", Qt::CaseInsensitive) or 
        fullFileName.startsWith("https://", Qt::CaseInsensitive) or
        fullFileName.startsWith("ftp://", Qt::CaseInsensitive) or
        fullFileName.startsWith("news://", Qt::CaseInsensitive) or
        fullFileName.startsWith("mailto:", Qt::CaseInsensitive) or
        fullFileName.startsWith("webdav://", Qt::CaseInsensitive)  )
       { 
         /* all ok */
       } else {
         fullFileName.prepend("file:///");  
       }
    bool wr = QDesktopServices::openUrl(QUrl(fullFileName));
    if (!wr) {
    QMessageBox::warning(0, tr("Error"),tr("Window Unable to open action file or dir  %1").arg(loc.toString()));
    }
return;
#endif
    
    /* linux */

     bool r = QDesktopServices::openUrl(loc);
    if (!r) {
    QMessageBox::warning(0, tr("Error"),tr("Linux Unable to open action file or dir  %1").arg(loc.toString()));
    }
    
}

IMO: mailto:user@domaine geht naturlich auch aber eben nicht ueberall und nicht portabel, hingegen pdf formulare gehen uberall wo acrobat reader installiert ist...



beispiel xfdf - fdf:
http://itext.ugent.be/library/com/lowag ... ister.xfdf
http://itext.ugent.be/library/com/lowag ... onForm.fdf

beispiel pdf formular:
http://ciz.ch/Ticket_Form.pdf mit latex gemacht..