- 功能简介:帮朋友做的自动登陆邮箱接收邮件,并把邮件保存到数据库,附件下载到工程目录。
- 环境:qtcreator5.4,MSVC2013-Opengl,数据库:mysql
- 用到的第三方库https://github.com/dbzhang800/QtMail.git
- 界面
- 源码:Qt pop3接收邮件并下载附件程序
- 主要代码
- 创建数据库并初始化显示
ui->setupUi(this);
ui->loginButton->setEnabled(true);
ui->logoffButton->setEnabled(false);
ui->updateButton->setEnabled(false);
ui->updateButton->hide();//没找到可以用这个的命令,暂时屏蔽掉
ui->labelLoading->hide();
m_mailCount=0;
m_loadedCount=0;
m_db=QSqlDatabase::addDatabase("QMYSQL");
m_db.setHostName("localhost");
m_db.setPort(3306);
m_db.setUserName("root");
m_db.setPassword("root123");//根据mysql的实际情况设定用户名和密码
if(!m_db.open())
{
QMessageBox::critical(this,tr("Error"),tr("open data base failed"));
qDebug()<<"1:"<<m_db.lastError();
return;
}
QSqlQuery query(m_db);
if(!query.exec("create database if not exists maildb default charset=utf8"))
{
QMessageBox::critical(this,tr("Error"),tr("create data base maildb failed"));
qDebug()<<"2:"<<query.lastError();
return;
}
//指定数据库编码
if(!query.exec("set names utf8 "))
{
QMessageBox::critical(this,tr("Error"),tr("set database encode failed"));
qDebug()<<"4:"<<query.lastError();
return;
}
query.exec("use maildb");
if(!query.exec("create table if not exists mailtable(mailindex int auto_increment primary key,subject varchar(128),sender varchar(128),content varchar(1024),attchment varchar(128),time varchar(64))default charset=utf8 auto_increment=1"))
{
QMessageBox::critical(this,tr("Error"),tr("create table mailtable failed"));
qDebug()<<"3:"<<query.lastError();
return;
}
m_dbmodel = new QSqlTableModel(this,m_db);
m_dbmodel->setTable("mailtable");
// 设置编辑策略
m_dbmodel->setEditStrategy(QSqlTableModel::OnManualSubmit);
ui->mailTableView->setModel(m_dbmodel);
m_dbmodel->select();
m_pop = new QxtPop3(this);
m_pop->sslSocket()->setProtocol(QSsl::TlsV1_0);
m_pop->sslSocket()->setPeerVerifyMode(QSslSocket::QueryPeer);
connect(m_pop, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(m_pop, SIGNAL(connected()), this, SLOT(connected()));
- 登陆
void MainWindow::on_loginButton_clicked()
{
QString hostname = ui->serverEdit->text();
int port = ui->portEdit->text().toInt();
QString username = ui->userEdit->text();
QString pass = ui->pawEdit->text();
m_pop->setUsername(username.toLocal8Bit());
m_pop->setPassword(pass.toLocal8Bit());
m_pop->setStartTlsDisabled(true);
m_pop->connectToHost(hostname.toLocal8Bit(), port);
}
发送list命令和retry命令获取邮件
//在update函数中发送list命令
void MainWindow::updateData()
{
ui->labelLoading->show();
m_mailCount=0;
m_loadedCount=0;
if (!m_pop->isConnected()) return;
QxtPop3Reply* reply = m_pop->messageList();
connect(reply, SIGNAL(finished(int)), this, SLOT(handleList(int)));
qDebug()<<"LIST sent";
}
//在槽函数中处理list的返回结果,逐条发送retry命令
void MainWindow::handleList(int code)
{
switch (code)
{
case QxtPop3Reply::OK:
qDebug()<<"LIST: OK received";
{
QxtPop3ListReply* reply = dynamic_cast<QxtPop3ListReply*>(sender());
if (reply == 0)
{
QMessageBox::critical(this,tr("warning"),tr("MainWindow::handleList: sender is not a QxtPop3ListReply"));
return;
}
m_mailCount= reply->list().size();
foreach (QxtPop3Reply::MessageInfo msginfo, reply->list())
{
qDebug()<<QString("message %1: %2 bytes").arg(msginfo.id).arg(msginfo.size);
//通过retry命令获得详情
QxtPop3Reply* reply = m_pop->retrieveMessage(msginfo.id);
connect(reply, SIGNAL(finished(int)), this, SLOT(handleRetr(int)));
qDebug()<<"RETR sent";
}
}
break;
case QxtPop3Reply::Aborted:
qDebug()<<"LIST aborted.";
break;
case QxtPop3Reply::Timeout:
qDebug()<<"LIST: time out.";
break;
default:
break;
}
}
//在槽函数中处理retry命令的返回结果,得到邮件的各部分内容,并保存附件
void MainWindow::handleRetr(int code)
{
switch (code)
{
case QxtPop3Reply::OK:
qDebug()<<"RETR: OK received";
{
QxtPop3RetrReply* reply = dynamic_cast<QxtPop3RetrReply *>(sender());
if (reply == 0)
{
QMessageBox::critical(this,tr("warning"),tr("MainWindow::handleRetr: sender is not a QxtPop3RetrReply"));
return;
}
if (m_msg!=NULL)
{
delete m_msg;
m_msg=NULL;
}
m_msg = reply->message();
//headers;
QHash<QString, QString> headers=m_msg->extraHeaders();
//判断改封邮件是否已经在数据库中
QSqlQuery query(m_db);
query.prepare("select * from mailtable where time=?");
query.addBindValue(headers["date"]);
if(!query.exec())
{
qDebug()<<"4:"<<query.lastError();
break;//sql语句执行错误,break
}
if(query.size()>0)
break; //数据库中已经有该条记录,break
if(!query.exec("select * from mailtable"))
{
qDebug()<<"5:"<<query.lastError();
break;//sql语句执行错误,break
}
QString subject=headers["subject"].toUtf8();
QString sender=headers["from"].toUtf8();
QString date=headers["date"].toUtf8();
QString body=m_msg->body();
QString content=mailContent(body).toUtf8();
QString attachment=NULL;
//attachment
if (m_msg->attachments().size() > 0)
{
//如果路径不存在创建路径
QString dirPath=QString("attchments/%1-%2").arg(query.size()+1).arg(subject);//attachments/1-subject/attachmentFile
QDir dir;
QString currentDir = dir.currentPath();//保存当前工作路径
if(!dir.exists(dirPath))
dir.mkpath(dirPath);
dir.setCurrent(dirPath);//更改执行路径
foreach(QString filename, m_msg->attachments().keys())
{
attachment.append(filename);
attachment.append(",");
//保存附件
QxtMailAttachment att = m_msg->attachment(filename);
QFile file(filename);
QIODevice::OpenMode flags = QIODevice::WriteOnly;
if (att.isText())
flags |= QIODevice::Text;
if(!file.open(flags))
{
qDebug()<<"6:"<<"save "<<filename<<" failed";
continue;
}
file.write(att.rawData());
file.close();
}
dir.setCurrent(currentDir);//恢复工作路径
attachment = attachment.left(attachment.length() - 1);//去掉最后的分号
}
attachment=attachment.toUtf8();
//保存到数据库
query.clear();
query.prepare("insert into mailtable(mailindex,subject,sender,content,attchment,time) values(?,?,?,?,?,?)");
query.addBindValue(0);
query.addBindValue(subject);
query.addBindValue(sender);
query.addBindValue(content);
query.addBindValue(attachment);
query.addBindValue(date);
if(!query.exec())
{
QMessageBox::critical(this,tr("Error"),tr("insert data failed"));
qDebug()<<"5:"<<query.lastError();
}
m_dbmodel->select();
}
break;
case QxtPop3Reply::Aborted:
qDebug()<<"RETR aborted.";
break;
case QxtPop3Reply::Timeout:
qDebug()<<"RETR: time out.";
break;
default:
break;
}
m_loadedCount++;
if(m_loadedCount==m_mailCount)
ui->labelLoading->hide();
}
- 退出登陆
void MainWindow::on_logoffButton_clicked()
{
if(m_pop!=NULL)
{
m_pop->quit();
m_pop->disconnect();
ui->loginButton->setEnabled(true);
ui->logoffButton->setEnabled(false);
}
}
-
运行结果如下图
- 程序界面
-
下载的附件
-
注意事项:
1、因为使用的是pop3命令,要在邮箱设置-》POP3/SMTP/IMAP开启POP3/SMTP和POP3/IMAP
2、安装mysql,并启动mysql服务。拷贝C:\Program Files (x86)\MySQL\MySQL Server 5.5\lib\libmysql.dll到C:\Qt\Qt5.4.0\5.4\msvc2013_opengl\bin,不然会出现数据库驱动没有加载的编译错误
3、只能接收开通POP3/SMTP和POP3/IMAP之后接收的邮件,之前的接收不到。
4、163邮箱以及qq企业邮箱测试ok,126邮箱和qq普通邮箱发完list命令后没收到返回,不知道原因