1.开启QQ邮箱SMTP服务
(1)进入邮箱后,在顶部找到设置,点击进入
(2)点击账号选项卡
(3)点击开启服务
(4)如果没有绑定手机,会有提示,要先绑定手机。绑定手机后生成授权码。保存好授权码,之后需要使用
(5)生成后可以返回页面,点击管理服务
(6)进去之后可以在授权码管理中对已经生成的授权码进行停用,如果忘记了之前的授权码,也可以点击生成授权码生成新的授权码
(7)生成授权码的时候需要发送一个短信,可以使用微信扫描二维码然后发送短信
2.SMTPClient-for-Qt简介
SmtpClient-for-Qt 是一个用 C++ 编写的开源项目,专为 Qt 框架设计。该项目的主要目的是为基于 Qt 的应用程序提供一个简单易用的 SMTP 客户端库,使得开发者能够轻松地通过 SMTP 协议发送电子邮件。该项目的主要功能包括:
  • 发送复杂电子邮件:支持发送包含文本、HTML、附件、内联文件等多种内容的复杂电子邮件
  • SMTP 协议支持:通过 SMTP 协议与邮件服务器进行通信
  • SSL 和 SMTP 认证:支持 SSL 加密连接和 SMTP 认证(PLAIN 和 LOGIN 方法)
  • MIME 支持:能够处理 MIME 格式的电子邮件,支持多种编码方式(如 7bit、8bit、base64 等)
  • 多收件人支持:可以向多个收件人发送邮件,支持不同类型的收件人(如 to、cc、bcc)
3.SMTPClient-for-Qt编译
(1)打开工程
解压下载好的压缩包,使用自己的Qt编译器打开工程(我使用的是Qt5.9.2),工程在SmtpClient-for-Qt-2.0\src下
(2)选择自己需要的环境,我这里选的是MSVC2015 32bit
(3)在项目名称上右键,点击重新构建
(4)在Qt5.9.2上编译报错如下,因为QRandomGenerator类是在Qt5.10之后才新增的,所以需要修改下这个随机数的代码
(5)打开mimemultipart.cpp文件,把
#include <QRandomGenerator>
修改为
#include <random>
(6)新增函数generate64
quint64 generate64()
{
        std::random_device rd;
        std::mt19937_64 gen(rd());
        std::uniform_int_distribution<quint64> dis;
        return dis(gen);
}
(7)把MimeMultiPart函数里边的
md5.addData(QByteArray().append(QRandomGenerator::global()->generate64()));
修改为
md5.addData(QByteArray().append(generate64()));
(8)修改前后对比
修改前:
修改后:
(9)mimemultipart.cpp修改后的代码
/*
  Copyright (c) 2011-2012 - Tőkés Attila
  This file is part of SmtpClient for Qt.
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  See the LICENSE file for more details.
*/
 
#include "mimemultipart.h"
#include <QIODevice>
#include <QTime>
#include <QCryptographicHash>
#include <random>
 
const QString MULTI_PART_NAMES[] = {
    "multipart/mixed",         //    Mixed
    "multipart/digest",        //    Digest
    "multipart/alternative",   //    Alternative
    "multipart/related",       //    Related
    "multipart/report",        //    Report
    "multipart/signed",        //    Signed
    "multipart/encrypted"      //    Encrypted
};
 
quint64 generate64()
{
    std::random_device rd;
    std::mt19937_64 gen(rd());
    std::uniform_int_distribution<quint64> dis;
 
    return dis(gen);
}
 
MimeMultiPart::MimeMultiPart(MultiPartType type)
{
    this->type = type;
    this->cType = MULTI_PART_NAMES[this->type];
    this->cEncoding = _8Bit;
 
    QCryptographicHash md5(QCryptographicHash::Md5);
    md5.addData(QByteArray().append(generate64()));
    cBoundary = md5.result().toHex();
}
 
MimeMultiPart::~MimeMultiPart() {
    foreach (MimePart *part, parts) {
        delete part;
    }
}
 
void MimeMultiPart::addPart(MimePart *part) {
    parts.append(part);
}
 
const QList<MimePart*> & MimeMultiPart::getParts() const {
    return parts;
}
 
void MimeMultiPart::writeContent(QIODevice &device) const {
    QList<MimePart*>::const_iterator it;
 
    for (it = parts.constBegin(); it != parts.constEnd(); it++) {
        device.write("--" );
        device.write(cBoundary.toLatin1());
        device.write("\r\n");
        (*it)->writeToDevice(device);
    };
 
    device.write("--");
    device.write(cBoundary.toLatin1());
    device.write("--\r\n");
}
 
 
void MimeMultiPart::setMimeType(const MultiPartType type) {
    this->type = type;
    this->cType = MULTI_PART_NAMES[type];
}
 
MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const {
    return type;
}
(10)重新编译之后会生成对应的dll和lib文件
4.SMTPClient-for-Qt使用
int win_test_main::send_email(QString &send_data,QString &error_str)
{
    if(sender_code.isEmpty() || sender_name.isEmpty() || sender_email.isEmpty() || receiver_name_list.isEmpty() || receiver_email_list.isEmpty()){
        error_str = QString("发送方或接收方的邮箱信息不完整");
        return -1;
    }
    MimeMessage message;

    EmailAddress sender(sender_email, sender_name);
    message.setSender(sender);

    for(int i = 0;i < receiver_name_list.length();i++){
        EmailAddress to(receiver_email_list[i], receiver_name_list[i]);
        message.addRecipient(to);
    }

    message.setSubject(QString("%1 老化测试结果").arg(test_project));

    MimeText text;
    text.setText(send_data);

    message.addPart(&text);

    // Now we can send the mail
    SmtpClient smtp("smtp.qq.com", 465, SmtpClient::SslConnection);

    smtp.connectToHost();
    if (!smtp.waitForReadyConnected()) {
        smtp.quit();
        error_str = "无法连接到主机";
        return -1;
    }

    smtp.login(sender_email, sender_code);
    if (!smtp.waitForAuthenticated()) {
        smtp.quit();
        error_str = "发送方邮箱登录失败";
        return -1;
    }

    smtp.sendMail(message);
    if (!smtp.waitForMailSent()) {
        smtp.quit();
        error_str = "发送邮件失败";
        return -1;
    }

    smtp.quit();
    return 0;
}
带附件的邮件发送
void MainWindow::on_pushButton_send_clicked()
{
    QString sender_name = ui->lineEdit_sender_name->text();
    QString sender_email = ui->lineEdit_sender_email->text();
    QString sender_code = ui->lineEdit_sender_code->text();
    QString recevier_name = ui->lineEdit_recevier_name->text();
    QString recevier_email = ui->lineEdit_recevier_email->text();
    QString send_data = ui->textEdit->toPlainText();

    MimeMessage message;

    EmailAddress sender(sender_email, sender_name);
    message.setSender(sender);

    EmailAddress to(recevier_email, recevier_name);
    message.addRecipient(to);

    message.setSubject(QString("QSMTP test"));

    MimeText text;
    text.setText(send_data);

    message.addPart(&text);

    QString filePath = "/home/xmr/test.txt";
    QFile file(filePath);

    MimeFile attachment(&file);
    message.addPart(&attachment);

    // Now we can send the mail
    SmtpClient smtp("smtp.qq.com", 465, SmtpClient::SslConnection);

    smtp.connectToHost();
    if (!smtp.waitForReadyConnected()) {
        smtp.quit();
        QMessageBox::information(this,"info","connect fail");
        //error_str = "无法连接到主机";
        return;
    }

    smtp.login(sender_email, sender_code);
    if (!smtp.waitForAuthenticated()) {
        smtp.quit();
        QMessageBox::information(this,"info","login fail");
        //error_str = "发送方邮箱登录失败";
        return;
    }

    smtp.sendMail(message);
    if (!smtp.waitForMailSent()) {
        smtp.quit();
        QMessageBox::information(this,"info","send fail");
        //error_str = "发送邮件失败";
        return;
    }

    QMessageBox::information(this,"info","send succ");

    smtp.quit();
}
带图片的邮件发送
void MainWindow::on_pushButton_send_clicked()
{
    QString sender_name = ui->lineEdit_sender_name->text();
    QString sender_email = ui->lineEdit_sender_email->text();
    QString sender_code = ui->lineEdit_sender_code->text();
    QString recevier_name = ui->lineEdit_recevier_name->text();
    QString recevier_email = ui->lineEdit_recevier_email->text();
    QString send_data = ui->textEdit->toPlainText();

    MimeMessage message;

    EmailAddress sender(sender_email, sender_name);
    message.setSender(sender);

    EmailAddress to(recevier_email, recevier_name);
    message.addRecipient(to);

    message.setSubject(QString("QSMTP test"));

    QString body = "<html><body>"
                   "<p>Here is an attached picture:</p>"
                   "<img src=\"cid:image_cid\" alt='Image'>"
                   "</body></html>";

    MimeHtml text;
    text.setHtml(body);

    // 将本地磁盘上的图片添加为资源,并设置 CID 参考
    QPixmap pix = this->grab();
    pix.save("test.png");
    QFile file("test.png");
    MimeInlineFile *imagePart = new MimeInlineFile(&file);
    imagePart->setContentType("image/png");
    imagePart->setContentId("image_cid"); // 对应于上面 HTML 中 cid 值
    message.addPart(imagePart);

    message.addPart(&text);

    // Now we can send the mail
    SmtpClient smtp("smtp.qq.com", 465, SmtpClient::SslConnection);

    smtp.connectToHost();
    if (!smtp.waitForReadyConnected()) {
        smtp.quit();
        QMessageBox::information(this,"info","connect fail");
        //error_str = "无法连接到主机";
        return;
    }

    smtp.login(sender_email, sender_code);
    if (!smtp.waitForAuthenticated()) {
        smtp.quit();
        QMessageBox::information(this,"info","login fail");
        //error_str = "发送方邮箱登录失败";
        return;
    }

    smtp.sendMail(message);
    if (!smtp.waitForMailSent()) {
        smtp.quit();
        QMessageBox::information(this,"info","send fail");
        //error_str = "发送邮件失败";
        return;
    }

    QMessageBox::information(this,"info","send succ");

    smtp.quit();
}
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐