#include "sendemail.h"
#include "qtimer.h"
//#define emailPI_DEBUG
//#define emailDTP_DEBUG
#ifndef QT_NO_EMAIL
#include "qtcpsocket.h"
#include <QFile>
#include <QFileInfo>
#include <memory.h>
QT_BEGIN_NAMESPACE
class emailCommand
{
public:
emailCommand(sendemail::Command cmd, QStringList raw);
int id;
sendemail::Command command;
QStringList rawCmds;
static QBasicAtomicInt idCounter;
};
QBasicAtomicInt emailCommand::idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
emailCommand::emailCommand(sendemail::Command cmd, QStringList raw)
: command(cmd), rawCmds(raw)
{
id = idCounter.fetchAndAddRelaxed(1);
}
class emailPI : public QObject
{
Q_OBJECT
public:
emailPI(QObject *parent = 0);
void connectToHost(const QString &host, quint16 port);
bool sendCommands(const QStringList &cmds);
bool sendCommand(const QString &cmd)
{ return sendCommands(QStringList(cmd)); }
void clearPendingCommands();
void abort();
QString currentCommand() const
{ return currentCmd; }
bool transferConnectionExtended;
signals:
void e_connectState(int);
void e_finished(const QString&);
void e_error(int, const QString&);
private slots:
void connected();
void connectionClosed();
void delayedCloseFinished();
void readyRead();
void error(QAbstractSocket::SocketError);
//void ConnectState(int);
private:
void timerEvent( QTimerEvent *event );
// the states are modelled after the generalized state diagram of RFC 959,
// page 58
enum State {
Begin,
Idle,
Waiting,
Success,
Failure
};
bool processReply();
bool startNextCmd();
QTcpSocket commandSocket;
QString replyText;
char replyCode[3];
State state;
QStringList pendingCommands;
QString currentCmd;
int m_emailPITime;
};
emailPI::emailPI(QObject *parent) :
QObject(parent),
transferConnectionExtended(true),
commandSocket(0),
state(Begin),
currentCmd(QString()),
m_emailPITime(0)
{
commandSocket.setObjectName(QLatin1String("emailPI_socket"));
connect(&commandSocket, SIGNAL(connected()),
SLOT(connected()));
connect(&commandSocket, SIGNAL(disconnected()),
SLOT(connectionClosed()));
connect(&commandSocket, SIGNAL(readyRead()),
SLOT(readyRead()));
connect(&commandSocket, SIGNAL(error(QAbstractSocket::SocketError)),
SLOT(error(QAbstractSocket::SocketError)));
}
void emailPI::timerEvent( QTimerEvent *event )
{
emit e_error(sendemail::NotConnected,sendemail::tr("Time out"));
killTimer(m_emailPITime);
m_emailPITime=0;
}
void emailPI::connectToHost(const QString &host, quint16 port)
{
//emit connectState(sendemail::HostLookup);
commandSocket.connectToHost(host, port);
}
bool emailPI::sendCommands(const QStringList &cmds)
{
if (!pendingCommands.isEmpty())
return false;
if (commandSocket.state() != QTcpSocket::ConnectedState || state!=Idle) {
emit e_error(sendemail::NotConnected, sendemail::tr("Not connected"));
return true; // there are no pending commands
}
pendingCommands = cmds;
startNextCmd();
return true;
}
void emailPI::clearPendingCommands()
{
pendingCommands.clear();
currentCmd.clear();
state = Idle;
}
void emailPI::connected()
{
state = Begin;
#if defined(emailPI_DEBUG)
// qDebug("emailPI state: %d [connected()]", state);
#endif
// try to improve performance by setting TCP_NODELAY
commandSocket.setSocketOption(QAbstractSocket::LowDelayOption, 1);
emit e_connectState(sendemail::Connected);
}
void emailPI::connectionClosed()
{
commandSocket.close();
emit e_connectState(sendemail::Unconnected);
}
void emailPI::delayedCloseFinished()
{
emit e_connectState(sendemail::Unconnected);
}
void emailPI::error(QAbstractSocket::SocketError e)
{
if (e == QTcpSocket::HostNotFoundError) {
emit e_connectState(sendemail::Unconnected);
emit e_error(sendemail::HostNotFound,
sendemail::tr("Host %1 not found").arg(commandSocket.peerName()));
} else if (e == QTcpSocket::ConnectionRefusedError) {
emit e_connectState(sendemail::Unconnected);
emit e_error(sendemail::ConnectionRefused,
sendemail::tr("Connection refused to host %1").arg(commandSocket.peerName()));
} else if (e == QTcpSocket::SocketTimeoutError) {
emit e_connectState(sendemail::Unconnected);
emit e_error(sendemail::ConnectionRefused,
sendemail::tr("Connection timed out to host %1").arg(commandSocket.peerName()));
}else if(e==QTcpSocket::NetworkError)
{
emit e_connectState(sendemail::Unconnected);
emit e_error(sendemail::NotConnected,
commandSocket.peerName());
}
}
void emailPI::readyRead()
{
killTimer(m_emailPITime);
m_emailPITime=0;
while (commandSocket.canReadLine()) {
// read line with respect to line continuation
QString line = QString::fromLatin1(commandSocket.readLine());
if (replyText.isEmpty()) {
if (line.length() < 3) {
// protocol error
return;
}
const int lowerLimit[3] = {1,0,0};
const int upperLimit[3] = {5,5,9};
for (int i=0; i<3; i++) {
replyCode[i] = line[i].digitValue();
if (replyCode[i]<lowerLimit[i] || replyCode[i]>upperLimit[i]) {
// protocol error
return;
}
}
}
QString endOfMultiLine;
endOfMultiLine[0] = '0' + replyCode[0];
endOfMultiLine[1] = '0' + replyCode[1];
endOfMultiLine[2] = '0' + replyCode[2];
endOfMultiLine[3] = QLatin1Char(' ');
QString lineCont(endOfMultiLine);
lineCont[3] = QLatin1Char('-');
QString lineLeft4 = line.left(4);
while (lineLeft4 != endOfMultiLine) {
if (lineLeft4 == lineCont)
replyText += line.mid(4); // strip 'xyz-'
else
replyText += line;
if (!commandSocket.canReadLine())
return;
line = QString::fromLatin1(commandSocket.readLine());
lineLeft4 = line.left(4);
}
replyText += line.mid(4); // strip reply code 'xyz '
if (replyText.endsWith(QLatin1String("\r\n")))
replyText.chop(2);
if (processReply())
replyText = QLatin1String("");
}
}
bool emailPI::processReply()
{
#if defined(emailPI_DEBUG)
// qDebug("emailPI state: %d [processReply() begin]", state);
if (replyText.length() < 400)
qDebug("emailPI recv: %d %s", 100*replyCode[0]+10*replyCode[1]+replyCode[2], replyText.toLatin1().constData());
else
qDebug("emailPI recv: %d (text skipped)", 100*replyCode[0]+10*replyCode[1]+replyCode[2]);
#endif
int replyCodeInt = 100*replyCode[0] + 10*replyCode[1] + replyCode[2];
switch (state) {
case Begin:
if (replyCodeInt == 220) {
state = Idle;
emit e_finished(sendemail::tr("Connected to host %1").arg(commandSocket.peerName()));
break;
}
// reply codes not starting with 1 or 2 are not handled.
return true;
case Waiting:
if (replyCodeInt != 250)
state = Failure;
else
state = Success;
break;
default:
// ignore unrequested message
return true;
}
// special actions on certain replies
if (replyCodeInt == 334) {
//username ok
state = Idle;
} else if (replyCodeInt == 235) {
// password ok
state = Idle;
emit e_connectState(sendemail::LoggedIn);
} else if (replyCodeInt == 354) {
// can write data
while(!pendingCommands.isEmpty())
{
startNextCmd();
}
}els
Qt下 基于smtp协议的邮件发送客户端源码 支持附件添加



在本文中,我们将深入探讨如何在Qt环境下使用SMTP(Simple Mail Transfer Protocol)协议构建一个邮件发送客户端,并且支持附件功能。Qt是一个跨平台的应用程序开发框架,广泛用于创建图形用户界面和其他应用程序。SMTP是互联网标准,用于在邮件服务器之间传输电子邮件。 我们需要了解SMTP的基本工作原理。SMTP是一种基于文本的协议,它定义了邮件服务器如何交换邮件。发送邮件的过程通常涉及三个主要步骤:连接到SMTP服务器、身份验证和发送邮件。 在Qt中,我们可以使用Qt网络模块来处理SMTP通信。特别是,`QTcpSocket`类可以用来建立与SMTP服务器的连接,而`QNetworkAccessManager`则可以用于异步请求,这样在发送邮件时不会阻塞主进程。这正是"描述"中提到的异步实现。 接下来,让我们关注邮件的构建。在Qt中,我们可以使用`QMimeMessage`类来创建和管理邮件内容。这个类允许我们设置收件人、抄送人、密送人、主题以及邮件正文。对于HTML格式的邮件,可以使用`setHtmlBody`方法;对于纯文本邮件,使用`setText`。 邮件的附件功能是通过`QMimeMultiPart`和`QMimeData`实现的。`QMimeMultiPart`可以创建一个包含多个部分的邮件,每个部分可以是不同的MIME类型,比如文本或图片。`QMimeData`则用于存储附件的数据,可以通过`QMimeMessage`的`addAttachment`方法将其附加到邮件中。 下面是一段示例代码,展示了如何在Qt中创建一个SMTP邮件客户端: ```cpp #include <QApplication> #include <QMailMessage> #include <QMailSmtpSession> #include <QMailNetworkConfiguration> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 配置SMTP服务器信息 QMailNetworkConfiguration config; config.setProtocol(QMailNetworkConfiguration::ProtocolSMTP); config.setHostName("smtp.example.com"); config.setPort(587); // 默认SMTP端口是25,但许多服务器使用587 config.setUser("your-email@example.com"); config.setPassword("your-password"); // 创建SMTP会话 QMailSmtpSession smtpSession(config); // 创建邮件 QMailMessage message; message.setFrom("your-email@example.com"); message.setTo("recipient@example.com"); message.setSubject("Test Email with Attachment"); message.setText("This is a test email."); // 添加附件 QMailMessage::Attachment attachment; attachment.setData("data.txt", "text/plain", "This is the content of the attachment."); message.addAttachment(attachment); // 发送邮件 if (smtpSession.send(message)) { qDebug() << "Email sent successfully."; } else { qDebug() << "Error sending email:" << smtpSession.errorString(); } return app.exec(); } ``` 以上代码展示了一个简单的邮件发送过程,包括设置SMTP服务器配置、创建邮件、添加附件和发送邮件。实际项目中,你可能需要处理更多细节,如错误处理、TLS/SSL加密、身份验证机制(如PLAIN, LOGIN, 或者 XOAUTH2)等。 Qt结合SMTP协议提供了一种强大的方式来构建邮件客户端,尤其适合那些希望在不阻塞用户界面的情况下发送邮件的应用程序。通过理解和利用Qt的网络和邮件功能,开发者可以轻松地实现这个功能,同时支持附件的发送。




























- 1

- #完美解决问题
- #运行顺畅
- #内容详尽
- #全网独家
- #注释完整
- 王屁稀2020-04-15根本不能添加附件,礼貌性给中分
- gongjiyue2018-12-12不错,值得参考
- bsaver2018-09-30编译通过,发送时候返回:Internal Error,没有找到解决办法

- 粉丝: 57
- 资源: 5
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- C#初学者的编程入门与实践基础教程
- PHP初学者的入门与实践基础教程
- JavaScript初学者的入门与实践基础教程
- AI大模型学习与使用入门基础教程
- 大学生实验报告编写基础教程:从入门到精通
- Matlab仿真入门与实践基础教程
- Cocos Creator快速上手与游戏开发基础教程
- 硬件开发入门:从原理到实践基础教程
- 蓝桥杯初学者的Python编程入门基础教程
- (源码)基于Python的IoT猫监控系统.zip
- (源码)基于Arduino的自动衣物折叠设备(StakeFolder).zip
- (源码)基于Arduino的pypilot舵机控制器.zip
- (源码)基于ESP32和蓝牙低能耗协议的GIF图像传输系统.zip
- (源码)基于Arduino的花型灯光装饰项目.zip
- (源码)基于Fiware平台的Interwatch健康监测项目.zip
- (源码)基于Node.js的Minecraft机器人ZMBot.zip


