Собственно пытаюсь сделать smtp клиент для отправки html письма. Письмо отправляется и кодировки нормально проходят кроме одного НО. Переодически выскакивает лаг в виде лишних пробелов посредине слова или знаков ??. Причем этот лаг смещается если менять текст
Выглядит что то типа:
Просим Вас, после оплаты уведомить нас о продлен ии
А в оригинале должно быть:
Просим Вас, после оплаты уведомить нас о продлении
Собственно навели на мысль, что данный дефект возникает при отправке сообщения серверу - байты сообщения сжираются функцией, которая принимает их за размер блока.
Вот собственно код клиента:
#include "smtp.h"
Smtp::Smtp(QString host, QString username, QString pass){
qDebug() << "### Smtp start";
smtphost = host;
smtpusername = username;
smtppass = pass;
}
void Smtp::SetHost(QString host, QString username, QString pass){
smtphost = host;
smtpusername = username;
smtppass = pass;
}
void Smtp::Send(const QString &from, const QString &to, const QString &subject, const QString &body){
int waittime = 500000;
this->from = from;
rcpt = to;
ErrorMSG.clear();
Timeout = waittime;
linesend = 0;
isconnected = false;
message = TimeStampMail()+"\n";
message.append("User-Agent: Qt SMTP client\n");
message.append("X-Accept-Language: en-us, en\n");
message.append("MIME-Version: 1.0\n");
message.append("To: " + to + "\n");
message.append("From: " + from + "\n");
message.append("Subject: " + subject + "\n");
message.append("Content-Type: text/html; charset=UTF-8;\n"); /* или txt */
message.append("Content-transfer-encoding: 8BIT\n\n\n\n");
message.append(body);
message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) );
message.replace( QString::fromLatin1( "\r\n.\r\n" ),QString::fromLatin1( "\r\n..\r\n" ) );
qDebug() << "### Launch mail compose.... " << from << to << subject << body;
qDebug() << "### Config server smtp connect to...... " << smtphost;
smtpsocket = new QTcpSocket(this);
connect( this, SIGNAL(ConnectorSuccess()), this, SLOT(ReadLiner()));
connect( this, SIGNAL(SendLine()), this, SLOT(PutSendLine()));
if (smtphost.size() > 0)
{
smtpsocket->connectToHost(smtphost, 587);
}
else
{
smtpsocket->connectToHost("localhost", 25);
}
if (smtpsocket->waitForConnected(Timeout))
{
qDebug() <<"### connected on " << smtphost;
if (smtpsocket->waitForReadyRead(Timeout))
{
qDebug() <<"### emit from waitForReadyRead connect go can read";
isconnected = true;
emit ConnectorSuccess();
}
}
else
{
emit ErrorCloseAll();
AddErrorLogs("Время ожидания подключения к STMP-серверу <<"+smtphost.toStdString()+">> истекло!");
}
}
void Smtp::ReadLiner(){
m_nNextBlockSize = 0;
if (isconnected) {
qDebug() << "### socketType = " << smtpsocket->socketType();
qDebug() << "### ReadLiner is start by textstream ";
int loops = 0;
while (smtpsocket->canReadLine()) {
loops++;
response = smtpsocket->readLine();
qDebug() << loops << " in line " << response;
}
if (response.size() > 0) {
RemoteServerName = response;
mailstatus = response.left(3);
qDebug() << "###Status=" << mailstatus;
if (mailstatus == "220") {
response="";
linesend = 1;
emit SendLine();
}
}else{
emit ErrorCloseAll();
}
}
}
Smtp::~Smtp(){
qDebug() << "### Smtp stop and delete ";
}
void Smtp::PutSendLine(){
int current = linesend;
qDebug() <<"### Go and Send line " << linesend;
switch(current) {
case 1:
response = SendLineAndGrab("ehlo localhost");
if (response.size() > 0) {
ErrorMSG.append(response);
qDebug() << "1---- " << response;
linesend = 2;
emit SendLine();
}else{
qDebug() << "Connection lost";
AddErrorLogs("Подключение потеряно!");
}
response ="";
break;
case 2:
response = SendLineAndGrab("AUTH LOGIN");
if (response.size() > 0) {
ErrorMSG.append(response);
qDebug() << "2---- " << response;
linesend = 3;
emit SendLine();
} else {
qDebug() << "Connection lost";
AddErrorLogs("Подключение потеряно на <<ehlo localhost>>!");
}
response ="";
break;
case 3:
response = SendLineAndGrab(encodeBase64(smtpusername));
if (response.size() > 0) {
ErrorMSG.append(response);
qDebug() << "3---- " << response;
linesend = 4;
emit SendLine();
} else {
qDebug() << "Connection lost";
AddErrorLogs("Подключение потеряно на запросе пользователя!");
}
response ="";
break;
case 4:
response = SendLineAndGrab(encodeBase64(smtppass));
qDebug() << "4---- " << response;
if (response.size() > 0) {
ErrorMSG.append(response);
if (response.contains("ok", Qt::CaseInsensitive) ||
response.contains("succeeded", Qt::CaseInsensitive)||response.contains("successful", Qt::CaseInsensitive) ) {
linesend = 5;
emit SendLine();
} else {
qDebug() << "Connection lost!";
AddErrorLogs("Неверный логин("+smtpusername.toStdString()+") или пароль("+smtppass.toStdString()+")!");
}
} else {
qDebug() << "Connection lost!!";
AddErrorLogs("Подключение потеряно на запросе пароля!");
}
response ="";
break;
case 5:
response = SendLineAndGrab("MAIL FROM: "+from);
qDebug() << "5---- " << response;
if (response.size() > 0) {
linesend = 6;
emit SendLine();
}
break;
case 6:
response = SendLineAndGrab("RCPT TO: "+rcpt);
qDebug() << "6---- " << response;
if (response.size() > 0) {
ErrorMSG.append(response);
response ="";
response = SendLineAndGrab("DATA");
if (!response.contains("not", Qt::CaseInsensitive)) {
ErrorMSG.append(response);
response ="";
linesend = 7;
emit SendLine();
}
}
response ="";
break;
case 7:
response = SendLineAndGrab(message+"\r\n.");
qDebug() << "7---- " << response;
if (response.size() && response.contains("ok", Qt::CaseInsensitive) ) {
ErrorMSG.append(response);
linesend = 8;
emit SendLine();
}
response ="";
break;
case 8:
SendLineAndGrab("QUIT");
break;
default:
qDebug() << "Last line ...";
emit ErrorCloseAll();
return;
break;
}
}
QString Smtp::SendLineAndGrab(QString senddata){
QString incommingData = "";
if (isconnected) {
/////////QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
int current = linesend;
int loops = 0;
qDebug() << "####Send" << current << "Now => " << senddata;
/*QByteArray arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
out << quint16(0) << senddata<<"\r\n";
out.device()->seek(0);
out << quint16(arrBlock.size() - sizeof(quint16));
qDebug()<<arrBlock.size();
smtpsocket->write(arrBlock);
qDebug()<<sizeof(senddata.toUtf8())*senddata.size();*/
senddata=senddata+"\r\n";
int size=sizeof(senddata.toUtf8())*senddata.size();
int real=smtpsocket->write(senddata.toUtf8());
qDebug()<<size<<"А было отправленно: "<<real;
if (senddata != "QUIT") {
if (smtpsocket->waitForReadyRead(Timeout)) {
while (smtpsocket->canReadLine()) {
loops++;
QString opera = smtpsocket->readLine()+"\n";
incommingData = opera + incommingData;
qDebug() << loops << "|#" << opera << "#|";
}
}
} else {
////////QApplication::restoreOverrideCursor();
delete smtpsocket;
isconnected = false;
emit SuccessQuit();
return incommingData;
}
///////QApplication::restoreOverrideCursor();
} else {
emit ErrorCloseAll();
}
return incommingData;
}
void Smtp::disconnected(){
qDebug() <<"disconneted";
qDebug() << "error " << smtpsocket->errorString();
}
void Smtp::connected(){
output.append("connected");
qDebug() << "Connected ";
}
QString Smtp::encodeBase64( QString xml ) {
QByteArray text;
text.append(xml);
return text.toBase64();
}
QString Smtp::decodeBase64( QString xml ) {
QByteArray xcode("");;
xcode.append(xml);
QByteArray precode(QByteArray::fromBase64(xcode));
QString notetxt = precode.data();
return notetxt;
}
QStringList Smtp::GetErrorlist(){
return ErrorMSG;
}
int Smtp::dateswap(QString form, uint unixtime ) {
QDateTime fromunix;
fromunix.setTime_t(unixtime);
QString numeric = fromunix.toString((const QString)form);
bool ok;
return (int)numeric.toFloat(&ok);
}
QString Smtp::TimeStampMail(){
/* mail rtf Date format! [url]http://www.faqs.org/rfcs/rfc788.html[/url] */
QDateTime timer1( QDateTime::currentDateTime() );
/////////timer1.setTimeSpec(Qt::UTC);
uint unixtime = timer1.toTime_t();
QDateTime fromunix;
fromunix.setTime_t(unixtime);
QStringList RTFdays = QStringList() << "giorno_NULL" << "Mon" << "Tue"
<< "Wed" << "Thu" << "Fri" << "Sat"
<< "Sun";
QStringList RTFmonth = QStringList() << "mese_NULL" << "Jan" << "Feb"
<< "Mar" << "Apr" << "May" << "Jun"
<< "Jul" << "Aug" << "Sep" << "Oct"
<< "Nov" << "Dec";
QDate timeroad(dateswap("yyyy",unixtime),
dateswap("M",unixtime), dateswap("d",unixtime));
qDebug() << "### RTFdays " << RTFdays.at(timeroad.dayOfWeek());
qDebug() << "### RTFmonth " << RTFmonth.at(dateswap("M",unixtime));
qDebug() << "### yyyy " << dateswap("yyyy",unixtime);
qDebug() << "### M " << dateswap("M",unixtime);
qDebug() << "### d " << dateswap("d",unixtime);
QStringList rtfd_line;
rtfd_line.clear();
rtfd_line.append("Date: ");
rtfd_line.append(RTFdays.at(timeroad.dayOfWeek()));
rtfd_line.append(", ");
rtfd_line.append(QString::number(dateswap("d",unixtime)));
rtfd_line.append(" ");
rtfd_line.append(RTFmonth.at(dateswap("M",unixtime)));
rtfd_line.append(" ");
rtfd_line.append(QString::number(dateswap("yyyy",unixtime)));
rtfd_line.append(" ");
rtfd_line.append(fromunix.toString("hh:mm:ss"));
rtfd_line.append(" +0100");
qDebug() << "### mail rtf Date format " << rtfd_line.join("");
return QString(rtfd_line.join(""));
}
Функция отправки - QString Smtp::SendLineAndGrab(QString senddata)
В документации функция записи в сокет имеет вид:
qint64 QIODevice::write ( const char * data, qint64 maxSize )
Как правильно посчитать размер сообщения в байтах. Так?
int size=sizeof(senddata.toUtf8())*senddata.size()
Если так тогда почему функция возвращает число отличное от size.
int real=smtpsocket->write(senddata.toUtf8());
qDebug()<<size<<"А было отправленно: "<<real;
4792 А было отправленно: 1810
PS прошу опощи разобраться в данной проблеме. =)