Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: merke от Сентябрь 08, 2010, 17:11



Название: Отправка сообщений по протоколу SMTP
Отправлено: merke от Сентябрь 08, 2010, 17:11
Несколько раз требовалось в программах реализовать отправку писем именно по протоколу SMTP, блуждал по форумам и ни как не мог найти существенной - простой реализации на кутях. Выбив маленько времени в графике решил написать свой класс, дабы в следующий раз не усложнять себе жизнь.

Выкладываю исходники класса. В приложении будет релиз консольного приложения.

smtp.h

Код:
#ifndef SMTP_H
#define SMTP_H

#include <QTcpSocket>
#include <QTextStream>

class smtp : public QObject
{
    Q_OBJECT
    
public:
    smtp(QString host, quint16 port);
    ~smtp();
    
    void set_Login(QString login); //Задаем логин
    void set_Password_for_login(QString password);//Задем пароль
    void set_Sender_mail(QString email);//Задаем отправителя
    void set_Recipient_mail(QString email);//Задаем получателя
    void set_Body_text(QString text);//Задаем текст тела сообщения
    void set_Subject(QString subject);//Задаем тему сообщения
    void send_Mail();//Отправка сообщенич
    
private:
    
    QString p_host;
    quint32 p_port;
    QString p_login;
    QString p_password;
    QString p_mail_From;
    QString p_mail_to;
    QString p_body;
    QString p_subject;
    
    QString message;
    
    int state;
    QString response;
    
    QTcpSocket *tcp;
    QTextStream *t;
    QString encodeBase64( QString xml );
    QString decodeBase64( QString xml );
    
  
    
    enum State {
            Init,  //Инициализация
            Start,
            Login,//Логин
            Pass, //Пароль
            Mail, //Отправитель
            Rcpt, //Получатель
            Data,
            Body, //Тело
            Quit,
            Close
        };

    
private slots:
    void on_connected();
    void on_read();

signals:
    void error_code(QString error_text);  
    void status( const QString & );
};

#endif // SMTP_H

smtp.cpp

Код:
#include <smtp.h>

smtp::smtp(QString host, quint16 port)
{

    p_host = host;
    p_port = port;
    tcp = new QTcpSocket();//Создаем экземляр объекта сокета
    t = new QTextStream(tcp);
    

    connect(tcp, SIGNAL(connected()),this, SLOT(on_connected()));
    connect(tcp, SIGNAL(readyRead()), this, SLOT(on_read()));
    connect(this, SIGNAL(status(QString)), this, SLOT(message_sended(QString)));
}

smtp::~smtp()
{

}


void smtp::send_Mail()
{
    if (p_login.isEmpty() || p_password.isEmpty())
        {
            emit error_code(QString::fromLocal8Bit("Логин или пароль не установлены"));
            return;
        }
    if (p_mail_From.isEmpty() || p_mail_to.isEmpty())
        {
            emit error_code(QString::fromLocal8Bit("Получатель или отправитель не задан"));
            return;
        }
    if (p_body.isEmpty())
        {
            emit error_code(QString::fromLocal8Bit("Тело сообщения не задано"));
            return;
        }
    if (p_subject.isEmpty())
        {
            emit error_code(QString::fromLocal8Bit("Тема сообщения не задана"));
            return;
        }
    
    tcp->abort();
    tcp->connectToHost(p_host, p_port);
    state = Init;
}

void smtp::on_connected()
{
    emit status("Connected to SMTP server");
}

void smtp::on_read()
{
    if( !tcp->canReadLine() )
        return;
    
    QString responseLine;
    
    do {
            responseLine = tcp->readLine();
            response += responseLine;
        } while( tcp->canReadLine() && responseLine[3] != ' ' );
    qDebug() << responseLine;
    responseLine.truncate( 3 );
    
    if ( state == Init && responseLine[0] == '2' )
        {
            
            *t << "HELO there\r\n";
            t->flush();
            state = Start;
        }
    else if (state == Start && responseLine[0] == '2')
        {
            *t << "AUTH LOGIN\r\n";
            t->flush();
            state = Login;
        }
    else if (state == Login && responseLine[0] == '3')
        {
            *t << encodeBase64(p_login) << "\r\n";
            t->flush();
            state = Pass;
        }
    else if (state == Pass && responseLine[0] == '3')
        {
            *t << encodeBase64(p_password) << "\r\n";
            t->flush();
            state = Mail;
        }
    else if ( state == Mail && responseLine[0] == '2' )
        {
            
            *t << "MAIL FROM: <" << p_mail_From << ">\r\n";
            t->flush();
            state = Rcpt;
        }
    else if ( state == Rcpt && responseLine[0] == '2' )
        {
            
            *t << "RCPT TO: <" << p_mail_to << ">\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' )
        {
            QString body;
            body = p_body;
            QString subject;
            subject = p_subject;
            message = QString::fromLatin1( "From: " ) + p_mail_From
                      +QString::fromLatin1( "\nTo: " ) + p_mail_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" ) );
            
            *t << message << "\n" << ".\r\n";
            t->flush();
            state = Quit;
        }
    else if ( state == Quit && responseLine[0] == '2' )
        {
            *t << "QUIT\r\n";
            state = Close;
            //t->flush();
            emit status( tr( "Message sent" ) );
        }
    else if ( state == Close )
        {
            
        }
    else
        {
            emit status(tr("Unknown answer from SMTP server"));
            state = Close;
        }
    response = "";  
}

void smtp::set_Login(QString login)
{
    p_login = login;
}

void smtp::set_Password_for_login(QString password)
{
    p_password = password;
}

void smtp::set_Sender_mail(QString email)
{
    p_mail_From = email;
}

void smtp::set_Recipient_mail(QString email)
{
    p_mail_to = email;
}

void smtp::set_Body_text(QString text)
{
    p_body = text;
}

void smtp::set_Subject(QString subject)
{
    p_subject = subject;
}

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;
}


Пример простой отправки:

  
Код:
 smtp *mail = new smtp("smtp.mail.ru", 25);
    mail->set_Login("mylnik@mail.ru");
    mail->set_Password_for_login("123456");
    mail->set_Sender_mail("mylnik@mail.ru");
    mail->set_Recipient_mail("vasya@mail.ru");
    mail->set_Subject(QString::fromLocal8Bit("Привет"));
    mail->set_Body_text("HI");
    mail->send_Mail();

Код может быть и не универсален! Жду критику=)


Поменять расширение вложения на .rar





Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Amigo_sa от Сентябрь 08, 2010, 17:59
очень полезный для меня класс, спасибо!
Пожелание, не могли бы вы выложить файл проекта, а то многие mingwm не имеют =). Хотя я и так код ручками копировал)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: merke от Сентябрь 08, 2010, 18:03
Вот вам сорсы, во вложении изменить расширение на .rar


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 08, 2010, 19:02
Код
C++ (Qt)
QString::fromLatin1( "From: " ) + p_mail_From+QString::fromLatin1( "\nTo: " ) + p_mail_to +QString::fromLatin1( "\nSubject: ") + subject +QString::fromLatin1( "\n\n" ) + body +"\n";
 

Этож песец так писать.. Не удержался ) Рекомендую глянуть в сторону функции QString::arg

Код
C++ (Qt)
QString( "From: %1\nTo: %2\nSubject: %3\n\n%4\n" ).arg(p_mail_From).arg(p_mail_to).arg(subject).arg(body);
 


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: merke от Сентябрь 08, 2010, 19:33
окей, учту! Да блин несколько лет писал на VB и всё остаются привычки=)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 08, 2010, 19:45
Видно что недавно на сях )

Вижу утечки:
Код:
smtp::smtp(QString host, quint16 port)
{
    ...
    tcp = new QTcpSocket();//Создаем экземляр объекта сокета
    t = new QTextStream(tcp);
    ...
}

smtp::~smtp()
{
    ???? пусто
}


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 08, 2010, 20:02
есть некий проект, но я не помню как зовется что-то типа qmp или qsmtp. Короче набор классов для работы с почтой, включая самописный сервак на Qt, реализацию pop, imap, smtp


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Amigo_sa от Сентябрь 08, 2010, 21:50
Видно что недавно на сях )

Вижу утечки:
Код:
smtp::smtp(QString host, quint16 port)
{
    ...
    tcp = new QTcpSocket();//Создаем экземляр объекта сокета
    t = new QTextStream(tcp);
    ...
}

smtp::~smtp()
{
    ???? пусто
}
Конечно это потенциальная ошибка, но если по логике программы класс smtp живет вместе с процессом всегда, то не страшно.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 08, 2010, 23:39
Цитировать
Конечно это потенциальная ошибка, но если по логике программы класс smtp живет вместе с процессом всегда, то не страшно.

Только потом, когда смотришь как кутэ течет, да как визуальные стили текут (qtcurve да oxygen), да остальные системные либы... переходы по не инициализированным переменным пачками...  не по себе как-то. Они видимо тоже так думают :)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: vadim303 от Сентябрь 09, 2010, 09:43
Видно что недавно на сях )

Вижу утечки:
Код:
smtp::smtp(QString host, quint16 port)
{
    ...
    tcp = new QTcpSocket();//Создаем экземляр объекта сокета
    t = new QTextStream(tcp);
    ...
}

smtp::~smtp()
{
    ???? пусто
}
Конечно это потенциальная ошибка, но если по логике программы класс smtp живет вместе с процессом всегда, то не страшно.
Чем хорош Qt - его классы спроектированы так, что сами удаляют из памяти все дочерние объекы, надо только не забывать у них parent указывать в конструкторе (если только это не визуальные объекты которые потом с помощью методов типа addWidget добавляют - тогда не обязательно и это). Если лень delete прописывать, достаточно в вашем случае указать в конструкторе родителя: QTcpSocket(this)

Edit:
Ну и чтобы ваш класс было так же удобно использовать, сделайте конструктор как полагается:
в smtp.h:
Код:
smtp(QString host, quint16 port, QObject *parent = 0);
в smtp.cpp:
Код:
smtp::smtp(QString host, quint16 port, QObject *parent) : QObject(parent)
{
  ...


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 09, 2010, 13:55
navrocky
а чем вы меряли утечки, простите? лично я их в Qt не нашел (вру, нашел 1). Возможно ваша тулза таки неправильно показывает?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 09, 2010, 16:15
Цитировать
а чем вы меряли утечки, простите? лично я их в Qt не нашел (вру, нашел 1). Возможно ваша тулза таки неправильно показывает?
Под линуксом - valgrind. Обычно он не ошибается. Часто кажется что он врет, но после долгих раскопок все-таки находишь )


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 09, 2010, 16:31
он врет:)
он тупит из-за статик переменных, насколько я знаю.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: varkon от Сентябрь 09, 2010, 17:47
он врет:)
он тупит из-за статик переменных, насколько я знаю.
а есть принципиальная разница - врет он или нет? Или в Qt реализован сборщик мусора? Оба ответа  - нет.
Выделенные ресурсы надо освобождать, либо использовать "умные указатели". Подход - "но если по логике программы ...." - был, есть и будет основным источником ошибок в приложениях.
З.Ы. Это относится к данному конкретному коду, а не к высказыванию о массовости memory licks от navrocky. Хотя в целом не так уж он и неправ. 


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 09, 2010, 17:57
я про Qt веду речь:) а в данном коде да, утечка и никакие "логики" ее не оправдывают


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 10, 2010, 09:24
З.Ы. Это относится к данному конкретному коду, а не к высказыванию о массовости memory licks от navrocky. Хотя в целом не так уж он и неправ. 

Почему же не прав :)
У меня большой проект, все свои ошибки работы с памятью я полечил (на мой код valgrind не ругается и все ошибки которые я нашел были по существу), однако у меня есть большой файл подавлений ошибок системных библиотек, и Qt в их числе...

Например, первое что попалось (qt 4.6.2):
Код:
src/gui/widgets/qdockarealayout.cpp:1936
>>> QDockAreaLayoutItem item(new QDockWidgetItem(widget));
Явная утечка, QDockAreaLayoutItem не освобождает его потом...

И так во многих системных библиотеках, в бусте, в ld.so и так далее.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 12, 2010, 14:49
тут передается виджет как параметр в конструкторе и ятп что док виджет айтем будет удален при удалении виджета


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 13, 2010, 10:22
тут передается виджет как параметр в конструкторе и ятп что док виджет айтем будет удален при удалении виджета

QDockWidgetItem -> QWidgetItem -> QLayoutItem

Не наследник QObject, автоматическое удаление не работает. Просмотри их конструкторы, там нигде нет регистрации у widget.. И оно конечно течет.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 13, 2010, 10:49
то, что не используется механизм родства куобжектов, не означает, что нет удаления руками. Настолько тупых ошибок в qt нет


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: SABROG от Сентябрь 13, 2010, 13:23
QMF (http://qt.gitorious.org/qt-labs/messagingframework) пробовали?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: ритт от Сентябрь 13, 2010, 15:19
Код
C++ (Qt)
QString::fromLatin1( "From: " ) + p_mail_From+QString::fromLatin1( "\nTo: " ) + p_mail_to +QString::fromLatin1( "\nSubject: ") + subject +QString::fromLatin1( "\n\n" ) + body +"\n";
 

Этож песец так писать.. Не удержался ) Рекомендую глянуть в сторону функции QString::arg

Код
C++ (Qt)
QString( "From: %1\nTo: %2\nSubject: %3\n\n%4\n" ).arg(p_mail_From).arg(p_mail_to).arg(subject).arg(body);
 

ой, не надо советовать херню :)
ваше QString( "From: %1\nTo: %2\nSubject: %3\n\n%4\n" ).arg(p_mail_From).arg(p_mail_to).arg(subject).arg(body); в разы медленнее перегруженного +=
а вот QString::fromLatin1() я бы заменил на QLatin1String() - для наглядности...


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 14, 2010, 11:36
Цитировать
ой, не надо советовать херню :)

Это не "херня". Если код не критичен к скорости исполнения (в данном случае это так), то format предпочтительнее, так как более наглядно и компактно выглядит, позволяет отформатировать вставляемые значения, поддается переводу.

Так что не надо ля-ля...  >:(

ЗЫЖ QLatinXXX здесь в любом случае лишний, т.к. в его коде нет специфичных для Latin-1 символов. И вообще в исходники должны быть в UTF-8 и строки грузиться через tr() и QString::fromUtf8


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: ufna от Сентябрь 14, 2010, 11:43
Так, а реально ::fromLatin1(..) быстрее чем .arg() пихать? Сильная разница?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 14, 2010, 12:19
Цитировать
Так, а реально ::fromLatin1(..) быстрее чем .arg() пихать? Сильная разница?

Я вот даже отвлекся и написал тест:
Код
C++ (Qt)
void test_various::test_plus_vs_format()
{
   int cnt = 1000000;
 
   QString res;
   QString p_mail_From = "mail@gavgav.ru";
   QString p_mail_to = "mail@gavgav.ru";
   QString subject = "My cool mega subject";
   QString body = QString("Body message ").repeated(10);
 
   LOG_DEBUG << "Started QString PLUS operator. Total %1 iterations", cnt;
   for (int i = 0; i < cnt; i++)
   {
       res = "From: " + p_mail_From + "\nTo: " + p_mail_to + "\nSubject: " +
               subject + "\n\n" + body + "\n";
   }
   LOG_DEBUG << "Finished plus";
 
   LOG_DEBUG << "Started QString .arg() function. Total %1 iterations", cnt;
   for (int i = 0; i < cnt; i++)
   {
       res = QString("From: %1\nTo: %2\nSubject: %3\n\n%4\n").arg(p_mail_From)
               .arg(p_mail_to).arg(subject).arg(body);
   }
   LOG_DEBUG << "Finished arg()";
}
 

Собирал релиз с оптимизаций -O2.

Результат тестирования:
Код:
2010-Sep-14 13:14:04.882129 D:    72 TH:0 (dbg )1 syslog: Thread #0 with id=0x83358e0
2010-Sep-14 13:14:04.882129 D:    72 TH:0 (dbg )1 test_various: Started QString PLUS operator. Total 1000000 iterations
2010-Sep-14 13:14:06.954295 D:2072166 TH:0 (dbg )1 test_various: Finished plus
2010-Sep-14 13:14:06.954465 D:   170 TH:0 (dbg )1 test_various: Started QString .arg() function. Total 1000000 iterations
2010-Sep-14 13:14:08.726525 D:1772060 TH:0 (dbg )1 test_various: Finished arg()
Смотрим поле D: - это разница в микросекундах от предыдущей записи в лог. Видим что вариант с плюсом выполнялся 2072 ms, а вариант с .arg() 1772 ms.

Выводы делайте сами ;)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Kolobok от Сентябрь 14, 2010, 12:52
Не совсем корректно. Попробуй добавить в тест изменяемый стринг. Например QString::number(i)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 14, 2010, 13:10
Код
C++ (Qt)
void test_various::test_plus_vs_format()
{
   int cnt = 1000000;
 
   QString res;
   QString p_mail_From = "mail@gavgav.ru";
   QString p_mail_to = "mail@gavgav.ru";
   QString subject = "My cool mega subject";
   QString body = QString("Body message ").repeated(10);
 
   LOG_DEBUG << "Started QString PLUS operator. Total %1 iterations", cnt;
   for (int i = 0; i < cnt; i++)
   {
       QString s_int = QString::number(i);
       res = "From: " + p_mail_From + "\nTo: " + p_mail_to + "\n" + s_int + "Subject: " +
               subject + "\n\n" + body + "\n";
   }
   LOG_DEBUG << "Finished plus";
 
   LOG_DEBUG << "Started QString .arg() function. Total %1 iterations", cnt;
   for (int i = 0; i < cnt; i++)
   {
       QString s_int = QString::number(i);
       res = QString("From: %1\nTo: %2\n%3Subject: %4\n\n%5\n").arg(p_mail_From)
               .arg(p_mail_to).arg(s_int).arg(subject).arg(body);
   }
   LOG_DEBUG << "Finished arg()";
}
 

Код:
2010-Sep-14 14:08:07.448952 D:    71 TH:0 (dbg )1 syslog: Thread #0 with id=0x8718bb8
2010-Sep-14 14:08:07.448952 D:    71 TH:0 (dbg )1 test_various: Started QString PLUS operator. Total 1000000 iterations
2010-Sep-14 14:08:10.661427 D:3212475 TH:0 (dbg )1 test_various: Finished plus
2010-Sep-14 14:08:10.661596 D:   169 TH:0 (dbg )1 test_various: Started QString .arg() function. Total 1000000 iterations
2010-Sep-14 14:08:13.565228 D:2903632 TH:0 (dbg )1 test_various: Finished arg()

3212 ms против 2903 ms. Опять же победа за .arg()..


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Авварон от Сентябрь 14, 2010, 13:49
проверьте на длинных строках - чтобы было много переалокаций


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Kolobok от Сентябрь 14, 2010, 13:53
У меня другие результаты
Код:
int cnt = 1000000;

 QString res;
 QString p_mail_From = "mail@gavgav.ru";
 QString p_mail_to = "mail@gavgav.ru";
 QString subject = "My cool mega subject";
 QString body = QString("Body message ").repeated(10);
 QTime time;


 qDebug() << "Started QString .arg() function. Total iterations" << cnt;
 time.start();
 for (int i = 0; i < cnt; i++)
 {
     res = QString("From: %1\nTo: %2\nSubject: %3\n\n%4\n%5").arg(p_mail_From)
             .arg(p_mail_to).arg(subject).arg(body).arg(QString::number(i));
 }
 qDebug() << "Finished arg()" << time.elapsed();
 qDebug() << "Started QString PLUS operator. Total iterations" << cnt;
 time.restart();
 for (int i = 0; i < cnt; i++)
 {
     res = "From: " + p_mail_From + "\nTo: " + p_mail_to + "\nSubject: " +
           subject + "\n\n" + body + "\n" + QString::number(i);
 }
 qDebug() << "Finished plus" << time.elapsed();

Цитировать
Started QString .arg() function. Total iterations 1000000
Finished arg() 8641
Started QString PLUS operator. Total iterations 1000000
Finished plus 6665


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 14, 2010, 14:55
У меня другие результаты

Странно. Какая система?
У меня AthlonX4, OpenSuse11.2 32bit, gcc 4.4.1, Qt 4.6.2.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Kolobok от Сентябрь 14, 2010, 15:21
Intel Core2 Duo, Win7, gcc 4.4.0, Qt 4.7


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: ритт от Сентябрь 14, 2010, 19:51
раз уж такие пляски,
QString::arg() - это поиск с заменой. причём, вставляемая подстрока обычно длиннее заменямой -> многократные выделения и копирования области памяти...

Цитировать
There are three ways you can access this improved method of string construction. The straightforward way is to include QStringBuilder wherever you want to use it, and use the '%' operator instead of '+' when concatenating strings:
     #include <QStringBuilder>

     QString hello("hello");
     QStringRef el(&hello, 2, 3);
     QLatin1String world("world");
     QString message =  hello % el % world % QChar('!');

A more global approach is to include this define:
     #define QT_USE_FAST_CONCATENATION

and use '%' instead of '+' for string concatenation everywhere. The third approach, which is the most convenient but not entirely source compatible, is to include two defines:
     #define QT_USE_FAST_CONCATENATION
     #define QT_USE_FAST_OPERATOR_PLUS

and the '+' will automatically be performed as the QStringBuilder '%' everywhere.

iirc, в 4.7 QT_USE_FAST_CONCATENATION объявлен по умолчанию, что уже даёт ощутимую оптимизацию; объявлением QT_USE_FAST_OPERATOR_PLUS включаем эту оптимизацию повсеместно для кода QString() + QString().

т.о. получаем всего одно выделение памяти и несколько копирований...
что быстрее?


зы. не бывает некритичного к производительности кода. нужно просто писать хороший код)
к примеру, если вы знаете, что передача параметра по ссылке быстрее, чем копирующий конструктор, вы же будете в функциях использовать ссылки, независимо от того, является ли код критичным к производительности или нет, верно?)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: navrocky от Сентябрь 15, 2010, 00:04
Но у .arg есть неоспоримые преимущества - наглядность и возможность перевода. Я его использую повсеместно, и только там где жмет производительность уже заморачиваюсь.

Потом, оптимизация суммирования строк - это новая фича начиная с 4.6 (я об этом и не знал даже). До этого было все уныло. И потом никто не мешает также соптимизировать функции форматирования также через билдер, я подозреваю что в одной из следующих версий и до нее доберутся.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: majatu от Апрель 28, 2011, 11:19
как-то не по теме разговор, лучше расскажите, как вложение отправить


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: CuteBunny от Апрель 29, 2011, 07:39
Код
C++ (Qt)
Content-Type: application/octet-stream; name=""
Content-Disposition: attachment; filename=""
Content-Transfer-Encoding: base64
 


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: daimon от Июнь 15, 2011, 17:19
Вот вам сорсы, во вложении изменить расширение на .rar
при создании rar есть выбор в zip


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: asrael от Сентябрь 11, 2012, 21:32
Отличная вещь! Только почему-то меняет в теме письма "_" на " ". Изменение кодировки дело не меняет..


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: PavelVX от Октябрь 18, 2012, 06:20
Подскажите пожалуйста: а можно как-то отправлять почту через почтового клиента по умолчанию? Для всех подобно этому коду нужно знать, адруса, smtp сервера. Но есть почтовый клиент уже настроенный. Можно ли через него отправлять письма с вложеним?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: virtual_root от Ноябрь 22, 2012, 12:56
спасибо за код, он прекрасно работает!


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Hirurg от Август 28, 2018, 12:02
Здравствуйте! К сожалению код уже не так прекрасно работает и серверы mail.ru отвечают "500 AUTH available only with SSL or TLS\r\n"
Подскажите пожалуйста, можно ли как-то модифицировать этот код с учётом изменения политики mail.ru относительно шифрования, и если да, то как?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Apktyc от Август 28, 2018, 12:37
Здравствуйте! К сожалению код уже не так прекрасно работает и серверы mail.ru отвечают "500 AUTH available only with SSL or TLS\r\n"
Подскажите пожалуйста, можно ли как-то модифицировать этот код с учётом изменения политики mail.ru относительно шифрования, и если да, то как?
Начать использовать QSslSocket для установки защищенного соединения. На 465 порте (обычно implicitTLS) должно хватить и этого. Для 587 порта (обычно explicitTLS) потребуется реализация ssl рукопожатия (STARTTLS и т.д.).
Не забываем подложить приложению библиотеки libeay32.dll, ssleay32.dll (проживают на дне океана в %QtPath%\Tools\%mingw%\opt\bin)


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Hirurg от Август 28, 2018, 12:49
Начать использовать QSslSocket для установки защищенного соединения. На 465 порте (обычно implicitTLS) должно хватить и этого. Для 587 порта (обычно explicitTLS) потребуется реализация ssl рукопожатия (STARTTLS и т.д.).
Не забываем подложить приложению библиотеки libeay32.dll, ssleay32.dll (проживают на дне океана в %QtPath%\Tools\%mingw%\opt\bin)
Спасибо за ответ! Продолжил копаться на форуме, прочитал про QSslSocket и решение пришло само собой  ;)
С библиотеками libeay32.dll, ssleay32.dll немножко пришлось помучаться, мне помогло следующее решение: https://forum.qt.io/topic/91777/qsslsocket-cannot-call-unresolved-function-sslv23_client_method (https://forum.qt.io/topic/91777/qsslsocket-cannot-call-unresolved-function-sslv23_client_method)
Если в двух словах, скачал с сайта http://slproweb.com/products/Win32OpenSSL.html (http://slproweb.com/products/Win32OpenSSL.html) инсталляцию Win32_OpenSSL_v1.0.2p.exe, и уже из неё взял нужные dll. С теми, которые на дне океана, не заработало


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Hirurg от Август 28, 2018, 18:03
Всё-таки надо прояснить ещё кое-что, а точнее кодировку темы сообщения.
Исходники хранятся в Utf-8 и выглядят так:
Цитировать
QString subject = QString::fromLocal8Bit("Тема письма");
QString body = QString::fromLocal8Bit("Текст сообщения");
По итогу текст сообщения отображается в полученном письме корректно, а тема выглядит как
Цитировать
Тема Ð¿Ð¸Ñ ÑŒÐ¼Ð°
Что делать, как правильно преобразовать строку для темы письма?


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: sergek от Август 28, 2018, 20:31
Знакомая проблема. Я использую библиотеку SmtpClient for Qt (Tőkés Attila), так там для того, чтобы избежать этих кракозябр, нужно отдельно задавать кодировку темы письма.
Код
C++ (Qt)
       MimeMessage message;
       message.setHeaderEncoding(MimePart::QuotedPrintable);
 
В самой библиотеке строка преобразования темы выглядит так (mimemessage.cpp):
Код
C++ (Qt)
   case MimePart::QuotedPrintable:
       mime += "=?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(subject)).replace(' ', "_").replace(':',"=3A") + "?=";
       break;
 
Ну и используется кодировка QuotedPrintable::encode (quotedprintable.cpp). Посмотрите исходники, думаю, разберетесь (я не вникал))
Кстати, проблема вылезала только на смартфонах, в mail.ru все было хорошо.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Apktyc от Август 28, 2018, 20:44
Надо смотреть заголовок письма, какая кодировка там.
utf-8?Q? - это quoted-printable;
utf-8?B? - base64.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: ssoft от Август 28, 2018, 21:16
Исходники хранятся в Utf-8 и выглядят так:
Цитировать
QString subject = QString::fromLocal8Bit("Тема письма");
QString body = QString::fromLocal8Bit("Текст сообщения");

Если исходники в utf-8, то должно быть
Код
C++ (Qt)
QString subject = QString::fromUtf8("Тема письма");
QString body = QString::fromUtf8("Текст сообщения");
 


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Hirurg от Август 29, 2018, 10:15
Если исходники в utf-8, то должно быть
QString subject = QString::fromUtf8("Тема письма");
QString body = QString::fromUtf8("Текст сообщения");
Вот так вообще ничего не читается, в заголовке вижу ���� ������


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Apktyc от Август 29, 2018, 10:29
Исходники не читай@сразу отвечай

Для варианта исходники в utf-8, в письме base64 делаю так:
Код
C++ (Qt)
QString Encoding = "UTF-8";
QString Subject = "Тема письма";
...
// Subject
Header += "Subject: =?" + Encoding + "?B?"
          + QByteArray().append(Subject).toBase64() + "?=\r\n";
 

Никаких лишних преобразований не делается.


Название: Re: Отправка сообщений по протоколу SMTP
Отправлено: Hirurg от Август 29, 2018, 16:35
Никаких лишних преобразований не делается.
Спасибо огромное, ваш ответ подтолкнул к решению проблемы! Преобразовывать к base64 я уже пробовал, а вот как прописать в явном виде кодировку темы, понял только теперь.
В общем, сделал вот так и всё заработало:
Код
C++ (Qt)
// Subject encoding
m_subject = "=?UTF-8?B?" + QByteArray().append(subject).toBase64() + "?=\r\n";
 
ещё раз спасибо!