title: Qt C++ simple SMTP Client
body: <p>I'm new to Qt.
  I found some example of simple SMTP server.
  It sends my email message, but program crashes after sending.</p>
  
  <p>Please, see error message and ouput:  </p>
  
  <p><a href="https://i.stack.imgur.com/Tt7bT.png" rel="nofollow noreferrer">screenshot</a></p>
  
  <p>I'm not allowed to publish photo, please help me.</p>
  
  <p>I cannot fix this problem. Please help me fix this stuff...
  Assertion error:</p>
  
  <blockquote>
    <p>Debug Assertion Failed: _CrtIsValidHeapPointer(block) 
    </blockquote></p>
    
    <p>EmailClient.h
    </p>
  
  
  <pre><code>#ifndef EMAILCLIENT_H
  #define EMAILCLIENT_H
  
  #include &lt;QtNetwork/QAbstractSocket&gt;
  #include &lt;QtNetwork/QSslSocket&gt;
  #include &lt;QString&gt;
  #include &lt;QTextStream&gt;
  #include &lt;QDebug&gt;
  #include &lt;QByteArray&gt;
  #include &lt;QFile&gt;
  #include &lt;QFileInfo&gt;
  #include &lt;QTextCodec&gt;
  
  
  class EmailClient : public QObject
  {
      Q_OBJECT
  public:
  
      EmailClient(const QString &amp;user, const QString &amp;pass,
            const QString &amp;host, quint16 port = 465, int timeout = 30000);
      EmailClient() = default;
  
      ~EmailClient();
  
      void sendMail(const QString &amp;to,
                     const QString &amp;subject, const QString &amp;body,
                     QStringList files = QStringList());
  
      QString getLastResponse() const;
  
      enum SendResult { Sent, Error, Timeout, CannotOpenAttachedFile, CannotFindAttachedFile };
      SendResult getSendResult() const;
  
  signals:
      void finished(int code);
  
  private slots:
      void errorReceived(QAbstractSocket::SocketError socketError);
      void disconnected();
      void connected();
      void readyRead();
  
  private:
      SendResult sendResult;
      int timeout;
      QString message;
      static QTextCodec *codecx;
  
      QTextStream t;
      QSslSocket socket;
      QString rcpt;
      QString response;
      QString user;
      QString pass;
      QString host;
      quint16 port;
      enum states { Tls, HandShake, Auth, User, Pass, Rcpt, Mail, Data, Init, Body, Quit, Close };
      int state;
  
      QString lastResponse;
  
      void initialize(const QString &amp;user, const QString &amp;pass,
                      const QString &amp;host, quint16 port, int timeout);
  
  };
  
  
  #endif // EMAILCLIENT_H
  </code></pre>
  
  <blockquote>
    <p>EmailClient.cpp
    </blockquote></p>
  
  
  <pre><code>#include "EmailClient.h"
  
  QTextCodec *EmailClient::codecx = QTextCodec::codecForName("UTF-8");
  
  EmailClient::EmailClient(const QString &amp;user, const QString &amp;pass, const QString &amp;host, quint16 port, int timeout )
  {
      initialize(user,pass, host, port, timeout);
  }
  
  
  void EmailClient::initialize(const QString &amp;user, const QString &amp;pass, const QString &amp;host, quint16 port, int timeout)
  {
      connect(&amp;socket, &amp;QSslSocket::readyRead, this, &amp;EmailClient::readyRead);
      connect(&amp;socket, &amp;QSslSocket::connected, this, &amp;EmailClient::connected);
      connect(&amp;socket, &amp;QSslSocket::disconnected, this, &amp;EmailClient::disconnected);
      connect(&amp;socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorReceived(QAbstractSocket::SocketError)));
  
      this-&gt;user = user;
      this-&gt;pass = pass;
  
      this-&gt;host = host;
      this-&gt;port = port;
      this-&gt;timeout = timeout;
  }
  
  void EmailClient::sendMail(const QString &amp;to, const QString &amp;subject, const QString &amp;body, QStringList files)
  {
      message = "To: " + to + "\n";
      message.append("From: " + user + "\n");
      //subject = "=?UTF-8?B?" + QByteArray().append(subject).toBase64() + "?=\r\n";
  
      //message.append("Subject: " + subject + "\n");
      message.append("Subject: =?UTF-8?B?" + QByteArray().append(subject).toBase64() + "?=\r\n");
      message.append("MIME-Version: 1.0\n");
      message.append("Content-Type: multipart/mixed; boundary=frontier\n\n");
  
      message.append( "--frontier\n" );
      //message.append( "Content-Type: text/html\n\n" );  //Uncomment this for HTML formating, coment the line below
      message.append( "Content-Type: text/plain\n\n" );
      message.append(body).append("\n\n");
  
      if (!files.isEmpty()) {
          qDebug() &lt;&lt; "Files to be sent: " &lt;&lt; files.size();
          for (const auto &amp;filePath : files) {
              QFile file(filePath);
              if (file.exists()) {
                  if (!file.open(QIODevice::ReadOnly)) {
                      qDebug() &lt;&lt; "Couldn't open file " + filePath;
                      lastResponse = "Couldn't open file " + filePath;
                      sendResult = SendResult::CannotOpenAttachedFile;
                      emit finished(sendResult);
                      return;
                  }
                  QByteArray bytes = file.readAll();
                  message.append("--frontier\n");
                  message.append("Content-Type: application/octet-stream\nContent-Disposition: attachment; filename=" + QFileInfo(file.fileName()).fileName() +";\nContent-Transfer-Encoding: base64\n\n");
                  message.append(bytes.toBase64()).append("\n");
              }
              else {
                  qDebug() &lt;&lt; "Couldn't find file " + filePath;
                  lastResponse = "Couldn't find file " + filePath;
                  sendResult = SendResult::CannotFindAttachedFile;
                  emit finished(sendResult);
                  return;
              }
          }
      }
  
      message.append( "--frontier--\n" );
  
      message.replace( QString::fromLatin1( "\n" ), QString::fromLatin1( "\r\n" ) );
      message.replace( QString::fromLatin1( "\r\n.\r\n" ),QString::fromLatin1( "\r\n..\r\n" ) );
  
  
      rcpt = to;
      state = Init;
      socket.connectToHostEncrypted(host, port);
      if (!socket.waitForConnected(timeout)) {
           qDebug() &lt;&lt; socket.errorString();
           lastResponse = socket.errorString();
           sendResult = SendResult::Timeout;
       }
  
      //t = new QTextStream(socket);
      t.setDevice(&amp;socket);
  
      t.setCodec(codecx);
  }
  
  EmailClient::~EmailClient()
  {
  
  }
  
  
  void EmailClient::errorReceived(QAbstractSocket::SocketError socketError)
  {
      qDebug() &lt;&lt; "Error: " &lt;&lt; socketError;
  }
  
  void EmailClient::disconnected()
  {
      qDebug() &lt;&lt;"Disconneted.";
      qDebug() &lt;&lt; "Error: "  &lt;&lt; socket.errorString();
      emit finished(sendResult);
  }
  
  void EmailClient::connected()
  {
      qDebug() &lt;&lt; "Connected to host.";
  }
  
  void EmailClient::readyRead()
  {
      QString responseLine;
      do {
          responseLine = socket.readLine();
          response += responseLine;
      }
      while (socket.canReadLine() &amp;&amp; responseLine[3] != ' ');
  
      responseLine.truncate(3);
  
      //qDebug() &lt;&lt; "Server response code: " &lt;&lt;  responseLine;
      qDebug() &lt;&lt; "Server response: " &lt;&lt; response;
  
      if (state == Init &amp;&amp; responseLine == "220") {
          t &lt;&lt; "EHLO localhost" &lt;&lt;"\r\n";
          t.flush();
          state = HandShake;
      }
      //No need, because I'm using socket.startClienEncryption() which makes the SSL handshake for you
      /*else if (state == Tls &amp;&amp; responseLine == "250")
      {
          // Trying AUTH
          qDebug() &lt;&lt; "STarting Tls";
          t &lt;&lt; "STARTTLS" &lt;&lt; "\r\n";
          t.flush();
          state = HandShake;
      }*/
      else if (state == HandShake &amp;&amp; responseLine == "250") {
          socket.startClientEncryption();
          if(!socket.waitForEncrypted(timeout)) {
              qDebug() &lt;&lt; socket.errorString();
              state = Close;
          }
          t &lt;&lt; "EHLO localhost" &lt;&lt; "\r\n";
          t.flush();
          state = Auth;
      }
      else if (state == Auth &amp;&amp; responseLine == "250") {
          // Trying AUTH
          t &lt;&lt; "AUTH LOGIN" &lt;&lt; "\r\n";
          t.flush();
          state = User;
      }
      else if (state == User &amp;&amp; responseLine == "334") {
          t &lt;&lt; QByteArray().append(user).toBase64()  &lt;&lt; "\r\n";
          t.flush();
          state = Pass;
      }
      else if (state == Pass &amp;&amp; responseLine == "334") {
          t &lt;&lt; QByteArray().append(pass).toBase64() &lt;&lt; "\r\n";
          t.flush();
  
          state = Mail;
      }
      else if (state == Mail &amp;&amp; responseLine == "235") {
          t &lt;&lt; "MAIL FROM:&lt;" &lt;&lt; user &lt;&lt; "&gt;\r\n";
          t.flush();
          state = Rcpt;
      }
      else if (state == Rcpt &amp;&amp; responseLine == "250") {
          t &lt;&lt; "RCPT TO:&lt;" &lt;&lt; rcpt &lt;&lt; "&gt;\r\n"; //r
          t.flush();
          state = Data;
      }
      else if (state == Data &amp;&amp; responseLine == "250") {
          t &lt;&lt; "DATA\r\n";
          t.flush();
          state = Body;
      }
      else if (state == Body &amp;&amp; responseLine == "354") {
          t &lt;&lt; message &lt;&lt; "\r\n.\r\n";
          t.flush();
          state = Quit;
      }
      else if (state == Quit &amp;&amp; responseLine == "250") {
          t &lt;&lt; "QUIT\r\n";
          t.flush();
          state = Close;
          lastResponse = "Message sent!";
          sendResult = SendResult::Sent;
      }
      else if (state == Close) {
          deleteLater();
          return;
      }
      else {
          qDebug() &lt;&lt; "Unexpected reply from SMTP server: " &lt;&lt; response;
          lastResponse = response;
          state = Close;
          sendResult = SendResult::Error;
      }
      response = "";
  }
  
  QString EmailClient::getLastResponse() const
  {
      return lastResponse;
  }
  
  
  EmailClient::SendResult EmailClient::getSendResult() const
  {
      return sendResult;
  }
  </code></pre>