[Qt C++] Send Email with attachments via SMTP

Sending emails is an interesting feature if you like to notify some event or send data from the software.....

Using the library "SmtpClient" created by bluetiger9 the set up of the application for sending emails is easier than Metal Gear Solid Very Easy Mode....

The things you can do with SmtpClient lib...

New in version 1.1:

             TLS (STARTTLS) connection is now supported
              multiple types of recipients (to, cc, bcc)
              nested mime emails (mixed/alternative, mixed/related)
              output compilant with RFC2045

SMPT Client for Qt supports

              TCP and SSL connections to SMTP servers
              SMTP authentication (PLAIN and LOGIN methods)
              sending MIME emails (to multiple recipients)
              plain text and HTML (with inline files) content in emails
              multiple attachments and inline files (used in HTML)
              different character sets (ascii, utf-8, etc) and encoding methods (7bit, 8bit, base64)
              error handling


So with this library you can do pretty much everything, just like using some regular mail client.

Note: this application is created using Qt 5.10 and msvc2017

First we need to create a project in Qt.

new email app



Then download the repository for the SmtpClient of bluetiger9 from Github or clone it using git

https://github.com/bluetiger9/SmtpClient-for-Qt


smtp client repo



Copy all the files on the "src" folder to a subfolder on your project..

You have to add all those files names on your .pro file also add "network" dependencies because we are going to use QTcpSocket and other stuffs....


add header

add network


After this run qmake so that all the files get included on the project...

run qmake


It is important that you go over all header files and remove  "SMTP_EXPORT" and  alsoremove #include "smtpexports.h", because the default of this library is to build on a dll....this has to be done on all header files.


remove smtp export



After that run build command to see if everything is working fine at this point..

Now I'm going to create a simple interface to use the email function.

email gui



I'm going to create all the send event when the button "SEND" has been clicked, but i'm going to divide it in 3 methods: separate the recipients, identify the attachments, and then send the message.

Go to mainwindow.h and include "SmtpMime" file , <QMessageBox> and also <QFileDialog>

include libs




Now create a slot for the clicked signal of the button "SEND"..

goto slot

slot clicked



Also create the slots for the clicked signal of the buttons to select the file to attach...


I'm going to use QFileDialog functions to get the path of the files I'm going to attach....this is done for each of the buttons...

   void MainWindow::on_tb_getAttach1_clicked(){
          QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("All Files (*.*)"));
         ui->le_emailAttach1->setText(fileName);
    }
    void MainWindow::on_tb_getAttach2_clicked(){
          QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("All Files (*.*)"));
           ui->le_emailAttach2->setText(fileName);
     }
    void MainWindow::on_tb_getAttach3_clicked(){
           QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("All Files (*.*)"));
            ui->le_emailAttach3->setText(fileName);
     }
     void MainWindow::on_tb_getAttach4_clicked(){
           QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("All Files (*.*)"));
           ui->le_emailAttach4->setText(fileName);
     }


Now go to the slot for the "SEND" button...

Its is important to check if the important fields like the username, password, port, smtp, and recipients fields are not empty....(this is a very very simple way to check those fields...a proper way will be to check if the format of each field is correct).


void MainWindow::on_pb_sendEmail_clicked(){
         if(ui->le_emailUser->text() != NULL && ui->le_emailPass->text() !=NULL){
              if(ui->le_emailPort->text().toInt() != NULL && ui->le_emailSmtp->text()!=NULL){
                    if(ui->le_sendersAdd->text() != NULL && ui->le_toAdd->text() != NULL){
                                 sendEmail();
                    }else QMessageBox::information(this,"Fill info", "please input senders addres and reciever addres");
              }else QMessageBox::information(this,"Fill info", "please input port and smtp");
        }else QMessageBox::information(this,"Fill info", "please input username and password");
}


Now if everything if filled (i'm not checking if it is in the proper format), call the sendEmail function..

Go to the sendEmail method and create the SmtpClient object with the smtp address, port and type of connection.

SmtpClient smtp(ui->le_emailSmtp->text(), ui->le_emailPort->text().toInt(), SmtpClient::SslConnection);

smtp.setUser(ui->le_emailUser->text());
smtp.setPassword(ui->le_emailPass->text());


Now create the Message object and set the senders address, name and subject.

MimeMessage message;

EmailAddress sender(ui->le_sendersAdd->text(), ui->le_sendersName->text());
message.setSender(&sender);
message.setSubject(ui->le_emailSubject->text());



Now for the recipients i'm going to create a simple function to separate each one of them (if there are various of them), because this library supports the carbon copy (cc) and the blind carbon copy (bcc).


QStringList MainWindow::getRecipientsAddress(QString str){
                QStringList recipients;
                recipients = str.split(QRegExp(";"));
                return recipients;
}

This assuming that all the address emails are separated by a semicolon...

Now I'm going to add the Recipients to the message..


QStringList to = getRecipientsAddress(ui->le_toAdd->text());
QStringList cc = getRecipientsAddress(ui->le_ccAdd->text());
QStringList bcc = getRecipientsAddress(ui->le_bccAdd->text());

for (QStringList::iterator it = to.begin();it != to.end(); ++it) {
           message.addRecipient(new EmailAddress(*it),MimeMessage::To);
}
for (QStringList::iterator it = cc.begin();it != cc.end(); ++it) {
            message.addRecipient(new EmailAddress(*it),MimeMessage::Cc);
}
for (QStringList::iterator it = bcc.begin();it != bcc.end(); ++it) {
          message.addRecipient(new EmailAddress(*it),MimeMessage::Bcc);
}


To add some text to the email i'm going to use the MimeText object, and add it to the message

MimeText text;
text.setText(ui->te_emailContent->document()->toPlainText());
message.addPart(&text);



To the attachments i must first check if they contain an address to some file...because i don't want those fields to be manually modifiable i set its property to "read only".



text field read only



Now add the valid attachments to the message

MimeAttachment attachment1(new QFile(ui->le_emailAttach1->text()));
MimeAttachment attachment2(new QFile(ui->le_emailAttach2->text()));
MimeAttachment attachment3(new QFile(ui->le_emailAttach3->text()));
MimeAttachment attachment4(new QFile(ui->le_emailAttach4->text())); 

if(ui->le_emailAttach1->text() != NULL){        
          message.addPart(&attachment1);
}

if(ui->le_emailAttach2->text() != NULL){        
         message.addPart(&attachment2);
}

if(ui->le_emailAttach3->text() != NULL){         
          message.addPart(&attachment3);
}
if(ui->le_emailAttach4->text() != NULL){         
          message.addPart(&attachment4);
}



the last thing is to connect to the host, login, and then send the message...


if (!smtp.connectToHost()) {
          QMessageBox::critical(this,"Fail to connect","cannot connect to host");
           return -1;
}
if (!smtp.login()) {
        QMessageBox::critical(this,"Fail to connect","Failed to login");
         return -2;
}
smtp.sendMail(message) 
      

QMessageBox::information(this,"Email Send","operation completed successfully!");
smtp.quit();



So now lets see if it works....
On the following test I'm using my gmail account and send it to my hotmail account, keep in mind that if you use Gmail you must activate first the two step verification so that you can create a password to access your email service...I'm sending 4 attachments.

test1



But probably your gonna get this error..

error host



If you look up at your application output console you'll see something like this...

error message


This is because we don't have the OpenSSL libraries installed, to solve this go to https://wiki.openssl.org/index.php/Binaries and download the precompiled binaries for your SO.

openssl


Because I'm using windows I'm going to download this one...

openssl for windows



Now copy "ssleay32.dll" and "libeay32.dll" on your executable file path.....now run again the application and send the message.....

send email ok


So this is all...hope you like it....the full code is stored on Github https://github.com/danalex07/qt-simpleemailapplication



SHARE

Daniel Sanin

    Blogger Comment
    Facebook Comment

0 comments :

Post a Comment