Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/58: Рейтинг темы: голосов - 58, средняя оценка - 4.62
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19

SMTP клиент на QT

15.04.2013, 10:48. Показов 11151. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Собственно пытаюсь сделать smtp клиент для отправки html письма. Письмо отправляется и кодировки нормально проходят кроме одного НО. Переодически выскакивает лаг в виде лишних пробелов посредине слова или знаков ??. Причем этот лаг смещается если менять текст
Выглядит что то типа:

Просим Вас, после оплаты уведомить нас о продлен ии

А в оригинале должно быть:

Просим Вас, после оплаты уведомить нас о продлении

Я так понимаю это что то с кодировками? Кто сталкивался с емаил рассылкой?

Листинг main.cpp

Листинг smtp клиента:

Господа. Подскажите куда копать. Не могу сориентироваться в чем может быть проблема.

PS Если кому то будет удобно взглянуть на итоговое письмо - могу выслать на email.

Скрин письма:

 Комментарий модератора 
Загрузите все данные на форум, не стоит использоваться другие сервисы!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.04.2013, 10:48
Ответы с готовыми решениями:

Smtp клиент для qt
добрый день, скачал библиотеку для отправки почты. Она работает, но! У нас есть домен mailовский при попытки авторизации выдает ошибку 535...

SMTP клиент - отправка сообщения
Доброго времени суток. Подскажите пожалуйста или направьте на литературу, как отправляется сообщение? Я создаю объект QTcpSocket,...

Отправка письма (заходим на почту). SMTP-клиент в С++
существует ли класс для работы с почтовыми серверами? например в делфи это делалось с помощью IdSMTP IdSMTP1.Host:='smtp.mail.ru'; ...

31
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
17.04.2013, 14:40  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от l_a_m Посмотреть сообщение
Как поток работает вообще представляете? грубо говоря труба, в одну сторону кинули с другой вылетело и ни как иначе.
Соответственно:

данные которые в senddata, нужно ловить на устройстве, которое соединено с потоком.
а readAll() и т.п. фишки нужно делать, когда сигнал получите, о том, что данные доступны или проверяйте bytesAvalible() или как-то так.

Спасибо за доходчивое пояснение. Пища для ума и направления движения появились. Щас будем дальше разбираться =)
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
18.04.2013, 17:45  [ТС]
Разбираю пример из учебника, и накопилось несколько вопросов.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef _MyClient_h_
#define _MyClient_h_
 
#include <QWidget>
#include <QTcpSocket>
 
class QTextEdit;
class QLineEdit;
 
class MyClient : public QWidget {
Q_OBJECT
private:
    QTcpSocket* m_pTcpSocket;
    QTextEdit*  m_ptxtInfo;
    QLineEdit*  m_ptxtInput;
    quint16     m_nNextBlockSize;
 
public:
    MyClient(const QString& strHost, int nPort, QWidget* pwgt = 0) ;
 
private slots:
    void slotReadyRead   (                            );
    void slotError       (QAbstractSocket::SocketError);
    void slotSendToServer(                            );
    void slotConnected   (                            );
};
#endif  //_MyClient_h_
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void MyClient::slotReadyRead()
{
    QDataStream in(m_pTcpSocket);
    in.setVersion(QDataStream::Qt_4_2);
    for (;;) {
        if (!m_nNextBlockSize) {
            if (m_pTcpSocket->bytesAvailable() < sizeof(quint16)) {
                break;
            }
            in >> m_nNextBlockSize;
        }
 
        if (m_pTcpSocket->bytesAvailable() < m_nNextBlockSize) {
            break;
        }
        QTime   time;
        QString str;
        in >> time >> str;
 
        m_ptxtInfo->append(time.toString() + " " + str);
        m_nNextBlockSize = 0;
    }
}
Поясните пожалуйста:

if (m_pTcpSocket->bytesAvailable() < sizeof(quint16)) {
Проверка условия это понятно. Но непонятно что такое sizeof(quint16). Как интерпретировать это условие?

in >> m_nNextBlockSize;
Что происходит в этой строке? я так понимаю переменной m_nNextBlockSize присваивается значение размера передаваемого потока?

Делаю фукнцию по аналогии:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
qDebug() << "### socketType = " << smtpsocket->socketType();
        qDebug() << "### ReadLiner is start by textstream ";
        QDataStream in(smtpsocket);
    int loops = 0;
 
    for (;;) {
    
    loops++;
    qDebug()<<m_nNextBlockSize<<" и "<<smtpsocket->bytesAvailable();
        if (!m_nNextBlockSize) {
            if (smtpsocket->bytesAvailable() < sizeof(quint16)) {
    qDebug()<<"Здесь №1";
                break;
            }
            in >> m_nNextBlockSize;
    
        }
 
        if (smtpsocket->bytesAvailable() < m_nNextBlockSize) {
        qDebug()<<"Здесь №2";
    qDebug()<<m_nNextBlockSize<<" и "<<smtpsocket->bytesAvailable();
    break;
    
        }
    
        QString str;
        in >> str;
    
        response.append(str);
    qDebug() << loops << " in line  " << response;
    m_nNextBlockSize = 0;
Размер входного потока передается переменной m_nNextBlockSize но вторую проверку не проходит.

### socketType = 0
### ReadLiner is start by textstream
0 и 104
Здесь №2
12850 и 102
Что я делаю не так? =)

Добавлено через 24 минуты
Кому будет удобнее код целиком:

smtp.h

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <QtNetwork>
#include "logger.h"
#include <QFile> 
 
 
class Smtp : public QObject {
    Q_OBJECT
public:
    Smtp(QString host, QString username, QString pass);
    ~Smtp();
    void SetHost(QString host, QString username, QString pass);
    void Send(const QString &from, const QString &to,
              const QString &subject, const QString &body);
    int linesend;
    QStringList ErrorMSG;
    QStringList GetErrorlist();
signals:
    void status( const QString &);
    void ConnectorSuccess();
    void SendLine();
    void ErrorCloseAll();
    void SuccessQuit();
private slots:
    void disconnected();
    void connected();
    void ReadLiner();
    void PutSendLine();
private:
    bool isconnected;
    QString smtphost;
    QString smtpusername;
    QString smtppass;
    QString message;
    QString output;
    QString RemoteServerName;
    QString mailstatus;
    QTextStream *t;
    QDataStream in;
    QDataStream out;
    quint8     m_nNextBlockSize;
    QTcpSocket *smtpsocket;
    QString from;
    QString rcpt;
    QString response;
    QString SendLineAndGrab(QString senddata);
    int Timeout;
    QString encodeBase64( QString xml );
    QString decodeBase64( QString xml );
    int dateswap(QString form, uint unixtime );
    QString TimeStampMail();
};


smtp.cpp

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
#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 = 5000;
    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 ";
        QDataStream in(smtpsocket);
    int loops = 0;
 
    for (;;) {
    
    loops++;
    qDebug()<<m_nNextBlockSize<<" и "<<smtpsocket->bytesAvailable()<<" и "<<sizeof(quint16);
        if (!m_nNextBlockSize) {
            if (smtpsocket->bytesAvailable() < sizeof(quint16)) {
    qDebug()<<"Здесь №1";
                break;
            }
            in >> m_nNextBlockSize;
    qDebug()<<m_nNextBlockSize<<" и "<<smtpsocket->bytesAvailable();
        }
 
        if (smtpsocket->bytesAvailable() < m_nNextBlockSize) {
        qDebug()<<"Здесь №2";
    break;
    
        }
    
        QString str;
        in >> str;
    
        response.append(str);
    qDebug() << loops << " in line  " << response;
    m_nNextBlockSize = 0;
        
    }
 
 
        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;
    out.device()->seek(0);
    out << quint16(arrBlock.size() - sizeof(quint16));
    smtpsocket->write(arrBlock);
        if (senddata != "QUIT") {
            if (smtpsocket->waitForReadyRead(Timeout)) {
 
 
 
 
    for (;;) {
    loops++;
        if (!m_nNextBlockSize) {
            if (smtpsocket->bytesAvailable() < sizeof(quint16)) {
                break;
            }
            in >> m_nNextBlockSize;
        }
 
        if (smtpsocket->bytesAvailable() < m_nNextBlockSize) {
            break;
        }
        QString str;
        in >> str;
    incommingData = str + incommingData;
        qDebug()<<loops << "|#" <<str<<"#|";
        m_nNextBlockSize = 0;
    }
 
 
 
 
 
              
            }
        } 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(""));
}
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
19.04.2013, 08:29
Цитата Сообщение от Aeooe Посмотреть сообщение
Проверка условия это понятно. Но непонятно что такое sizeof(quint16). Как интерпретировать это условие?
Передается двухбайтовое число, которое обозначает размер блока данных, потом передается блок данных.
Если нам пришло меньше двух байтов, то ожидаем пока придет остаток.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
19.04.2013, 10:54  [ТС]
Спасибо за пояснение Dmitriy_M =)

Что то в примере из учебника либо не договаривается либо неверно:

Функция чтения данных из потока:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void Smtp::ReadLiner(){
    m_nNextBlockSize = 0;
    if (isconnected) {
        qDebug() << "### socketType = " << smtpsocket->socketType();
        qDebug() << "### ReadLiner is start by textstream ";
        QDataStream in(smtpsocket);
    int loops = 0;
 
    for (;;) {
    
    loops++;
        if (!m_nNextBlockSize) {
            if (smtpsocket->bytesAvailable() < sizeof(quint16)) {
    qDebug()<<"Здесь №1"<<loops;
                break;
            }
            in >> m_nNextBlockSize;
    qDebug()<<m_nNextBlockSize<<" и "<<smtpsocket->bytesAvailable();
        }
 
        if (smtpsocket->bytesAvailable() < m_nNextBlockSize) {
    qDebug()<<"Здесь №2"<<loops;
    break;
        }
    
        QString str;
        in >> str;
    
        response.append(str);
    qDebug() << loops << " in line  " << response;
    m_nNextBlockSize = 0;
        
    }
 
 
        if (response.size() > 0) {
        RemoteServerName = response;
        mailstatus = response.left(3);
        qDebug() << "###Status=" << mailstatus;
            if (mailstatus == "220") {
                response="";
                linesend = 1;
                emit SendLine();
            }
        }else{
    qDebug()<<"Здесь №3";
            emit ErrorCloseAll();
        }
    }
}
Вывод функции следующий:

### socketType = 0
### ReadLiner is start by textstream
12850 и 102
Здесь №2 1
Здесь №3
Как вообще так может быть? По коду выходит что не проходит проверку второе условие
if (smtpsocket->bytesAvailable() < m_nNextBlockSize) {
qDebug()<<"Здесь №2"<<loops;
break;
}
Здесь написано что метод bytesAvailable() возвращает значение типа virtual qint64 мы же его сравниваем со значение типа quint16(m_nNextBlockSize). Правда читал что :

qint 32 - это обычный int, quint 16 - short, quint 8 - byte.
quint64 - unsigned long и т.д.
Выходит тут проблемы не должно возникать? Что вообще проверяет это условие? Что сообщение получено не полностью? Тогда зачем break(он завершает цикл)?

Почему переменная m_nNextBlockSize принимает значение 12850?
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
19.04.2013, 11:12
Цитата Сообщение от Aeooe Посмотреть сообщение
Как вообще так может быть? По коду выходит что не проходит проверку второе условие
Цитата Сообщение от Aeooe Посмотреть сообщение
Что вообще проверяет это условие?
Тебе приходится делать проверку на соответствие протоколу, т.к. кто угодно может послать что угодно, если не будет проверок сервер ляжет.

Цитата Сообщение от Aeooe Посмотреть сообщение
Тогда зачем break(он завершает цикл)?
да, иначе обработка сообщений остановиться.

Цитата Сообщение от Aeooe Посмотреть сообщение
Почему переменная m_nNextBlockSize принимает значение 12850?
Спроси у автора протокола.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
19.04.2013, 12:02  [ТС]
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Тебе приходится делать проверку на соответствие протоколу, т.к. кто угодно может послать что угодно, если не будет проверок сервер ляжет.
bytesAvailable() возвращает число байт, доступных для чтения. В условии проверяется число байт, доступных для чтения < m_nNextBlockSize(по моей логике должен равняться число байт, которые уже пришли в потоке. И тогда это условие просто завершает цикл. По факту как это обстоит? ). Все равно непонятно для чего это условие. Поясните поподробнее пожалуйста.

У меня клиентское приложение.

Протокол smtp.

Добавлено через 9 минут
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Спроси у автора протокола.
Протокол SMTP и сообщения передаются в виде текста.

Добавлено через 8 минут
развер размер доступных для чтения байт, возвращаемых bytesAvailable() может быть меньше m_nNextBlockSize(которые я полагаю тоже в байтах измеряются?)
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
19.04.2013, 12:26
Цитата Сообщение от Aeooe Посмотреть сообщение
о моей логике должен равняться число байт, которые уже пришли в потоке. И тогда это условие просто завершает цикл. По факту как это обстоит?
С чего это? Если размер сообщения не влезает в MTU, то будет все разбито на куча пакетов, которые приходят в произвольном порядке, с разной задержкой. Клиент/Сервер может не оперативно обрабатывать, то что ему придет.
Клиент/Сервер может послать несколько последовательных сообщений, и в этом случае bytesAvailable() может быть > m_nNextBlockSize.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
19.04.2013, 12:52  [ТС]
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Клиент/Сервер может послать несколько последовательных сообщений, и в этом случае bytesAvailable() может быть > m_nNextBlockSize.
bytesAvailable() показывает размер последнего пакета или всего ответа от сервера?
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
19.04.2013, 16:38
Цитата Сообщение от Aeooe Посмотреть сообщение
bytesAvailable() показывает размер последнего пакета или всего ответа от сервера?
Это количество доступных данных, для чтения из сокета.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
22.04.2013, 15:26  [ТС]
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Это количество доступных данных, для чтения из сокета.
Что-то вы меня запутали. =) Поясните как должен работать этот код?
Что есть метод bytesAvailable() и какое значение он имеет?
m_nNextBlockSize какую роль играет в этом цикле? Я так понял что эта переменная для проверки пришло ли сообщение(первое условие)? Полученно ли сообщение полностью(второе условие)?

И собственно в чем моя ошибка? почему я не могу читать сообщение от сервера? Возможно ошибка в механизме сигналов?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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()+">> истекло!");
    }
у меня не используется стандартный набор сигналов сокетов.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
24.04.2013, 10:37  [ТС]
Хьюстон, у нас проблемы. Помогите дельным советом.
0
0 / 0 / 0
Регистрация: 15.04.2013
Сообщений: 19
26.04.2013, 10:40  [ТС]
С чтением разобрался стандартными методами класса socket

КОД
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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();
        }
    }
    
}


Собственно теперь пытаюсь правильно отправить ответ на сервер. Как говорил ранее первом посте - возникают проблемы при отправке html писем на smtp сервера(пробовал mail, yandex, google). Проблема заключается в произвольных разрывах текста. Один человек посоветовал разобраться в способе записи данных в поток(якобы проблема кроется в этом). Я решил сделать аналогично учебнику используя классы QByteArray и QDataStream(что позволяет нам хранить текст запроса серверу в виде массива байт). Редактирую функцию относительно примера учебника:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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;
    out.device()->seek(0);
    out << quint16(arrBlock.size() - sizeof(quint16));
    qDebug()<<"Вывод в сокет - "<<arrBlock;
    smtpsocket->write(arrBlock+ "\r\n");
    /*smtpsocket->write(senddata. + "\r\n");*/
        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;
}
Пробую вывести значение переменной arrBlock - выводит пустую строку.

Вывод в сокет - ""
Я неверно вывожу или строка senddata не присваивается переменной?

Добавлено через 18 минут
Вот этот код выводит и говорит нам что данные всетаки записываются...

C++
1
2
3
4
5
6
7
8
QByteArray  arrBlock;
    qDebug()<<"ВЫвод до -"<<arrBlock.length();
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out << quint16(0) << senddata;
    out.device()->seek(0);
    out << quint16(arrBlock.size() - sizeof(quint16));
    qDebug()<<"Вывод после -"<<arrBlock.length();
    smtpsocket->write(arrBlock+ "\r\n");
Добавлено через 2 часа 37 минут
Собственно почему я хочу вывести QByteArray arrBlock в qDebug(). Дело в том, что программа отвечает:
####Send 1 Now => "ehlo localhost"
1 |# "502 5.5.2 Syntax error, command unrecognized.

" #|
1---- "502 5.5.2 Syntax error, command unrecognized.

"
### Go and Send line 2
####Send 2 Now => "AUTH LOGIN"
1 |# "502 5.5.2 Syntax error, command unrecognized.

" #|
2---- "502 5.5.2 Syntax error, command unrecognized.

"
### Go and Send line 3
####Send 3 Now => "YXV0b2luZm9ybWVyQGJpdGNvbTMyLnJ1"
1 |# "502 5.5.2 Syntax error, command unrecognized.

" #|
3---- "502 5.5.2 Syntax error, command unrecognized.

"
### Go and Send line 4
####Send 4 Now => "QDEyM3F3ZSQ="
1 |# "502 5.5.2 Syntax error, command unrecognized.

" #|
4---- "502 5.5.2 Syntax error, command unrecognized.

"
Connection lost!
### Smtp stop and delete
Если писать сообщения прямо в socket - соответственно все проходит.

C++
1
smtpsocket->write(senddata.toUtf8() + "\r\n");
Добавлено через 17 часов 44 минуты
В документации функция записи в сокет имеет вид:
qint64 QIODevice::write ( const char * data, qint64 maxSize )
Как правильно посчитать размер сообщения в байтах. Так?
C++
1
int size=sizeof(senddata.toUtf8())*senddata.size()
Если так тогда почему функция возвращает число отличное от size.

C++
1
2
int real=smtpsocket->write(senddata.toUtf8());
    qDebug()<<size<<"А было отправленно: "<<real;
4792 А было отправленно: 1810
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.04.2013, 10:40

Привязать отправку письма через SMTP клиент к QProgressBar
Уважаемые, подкиньте идею: к чему привязать progressbar при отправке письма?

Enc 28J60 telnet клиент или SMTP клиент
Всем привет. Если ли работающие библиотеки и скетчи для этой платы? В основном все для W5100 (( Спасибо

Smtp, почтовый клиент
Пишу программу для отправки почты используя протокол SMTP. Как я могу в программе получить служебный заголовок письма, где указана вся...

Smtp-клиент (Shell)
С Netcat-ом не подружилась, прошу помощи, подсказки в решении следующей задачи: Используя утилиту netcat реализовать простейший...

SMTP клиент и OpenSSL
Здравствуйте. Мне нужно написать простой SMTP клиент,но я столкнулся с небольшой проблемой.Чтобы &quot;общаться&quot; с SMTP сервером...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru