新增邮件发送工具
parent
6a0d95012a
commit
1d371bef97
|
@ -26,4 +26,5 @@
|
||||||
| 23 | zhtopy | 汉字转拼音 |
|
| 23 | zhtopy | 汉字转拼音 |
|
||||||
| 24 | qwtdemo | qwt的源码版本,无需插件,直接源码集成到你的项目即可 |
|
| 24 | qwtdemo | qwt的源码版本,无需插件,直接源码集成到你的项目即可 |
|
||||||
| 25 | buttondefence | 通用按钮地图效果 |
|
| 25 | buttondefence | 通用按钮地图效果 |
|
||||||
| 25 | mouseline | 鼠标定位十字线 |
|
| 26 | mouseline | 鼠标定位十字线 |
|
||||||
|
| 27 | email | 邮件发送工具 |
|
|
@ -0,0 +1,27 @@
|
||||||
|
#-------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project created by QtCreator 2016-09-29T13:23:25
|
||||||
|
#
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
QT += core gui network sql xml
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
TARGET = emailtool
|
||||||
|
TEMPLATE = app
|
||||||
|
MOC_DIR = temp/moc
|
||||||
|
RCC_DIR = temp/rcc
|
||||||
|
UI_DIR = temp/ui
|
||||||
|
OBJECTS_DIR = temp/obj
|
||||||
|
DESTDIR = bin
|
||||||
|
|
||||||
|
CONFIG += warn_off
|
||||||
|
SOURCES += main.cpp
|
||||||
|
SOURCES += frmemailtool.cpp
|
||||||
|
HEADERS += frmemailtool.h
|
||||||
|
FORMS += frmemailtool.ui
|
||||||
|
|
||||||
|
include ($$PWD/sendemail/sendemail.pri)
|
||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
INCLUDEPATH += $$PWD/sendemail
|
|
@ -0,0 +1,104 @@
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#include "frmemailtool.h"
|
||||||
|
#include "ui_frmemailtool.h"
|
||||||
|
#include "qfiledialog.h"
|
||||||
|
#include "qmessagebox.h"
|
||||||
|
#include "sendemailthread.h"
|
||||||
|
|
||||||
|
frmEmailTool::frmEmailTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmEmailTool)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->initForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
frmEmailTool::~frmEmailTool()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void frmEmailTool::initForm()
|
||||||
|
{
|
||||||
|
ui->cboxServer->setCurrentIndex(1);
|
||||||
|
connect(SendEmailThread::Instance(), SIGNAL(receiveEmailResult(QString)),
|
||||||
|
this, SLOT(receiveEmailResult(QString)));
|
||||||
|
SendEmailThread::Instance()->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void frmEmailTool::on_btnSend_clicked()
|
||||||
|
{
|
||||||
|
if (!check()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendEmailThread::Instance()->setEmialTitle(ui->txtTitle->text());
|
||||||
|
SendEmailThread::Instance()->setSendEmailAddr(ui->txtSenderAddr->text());
|
||||||
|
SendEmailThread::Instance()->setSendEmailPwd(ui->txtSenderPwd->text());
|
||||||
|
SendEmailThread::Instance()->setReceiveEmailAddr(ui->txtReceiverAddr->text());
|
||||||
|
|
||||||
|
//设置好上述配置后,以后只要调用Append方法即可发送邮件
|
||||||
|
SendEmailThread::Instance()->append(ui->txtContent->toHtml(), ui->txtFileName->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
void frmEmailTool::on_btnSelect_clicked()
|
||||||
|
{
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
dialog.setFileMode(QFileDialog::ExistingFiles);
|
||||||
|
|
||||||
|
if (dialog.exec()) {
|
||||||
|
ui->txtFileName->clear();
|
||||||
|
QStringList files = dialog.selectedFiles();
|
||||||
|
ui->txtFileName->setText(files.join(";"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool frmEmailTool::check()
|
||||||
|
{
|
||||||
|
if (ui->txtSenderAddr->text() == "") {
|
||||||
|
QMessageBox::critical(this, "错误", "用户名不能为空!");
|
||||||
|
ui->txtSenderAddr->setFocus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->txtSenderPwd->text() == "") {
|
||||||
|
QMessageBox::critical(this, "错误", "用户密码不能为空!");
|
||||||
|
ui->txtSenderPwd->setFocus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->txtSenderAddr->text() == "") {
|
||||||
|
QMessageBox::critical(this, "错误", "发件人不能为空!");
|
||||||
|
ui->txtSenderAddr->setFocus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->txtReceiverAddr->text() == "") {
|
||||||
|
QMessageBox::critical(this, "错误", "收件人不能为空!");
|
||||||
|
ui->txtReceiverAddr->setFocus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui->txtTitle->text() == "") {
|
||||||
|
QMessageBox::critical(this, "错误", "邮件标题不能为空!");
|
||||||
|
ui->txtTitle->setFocus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void frmEmailTool::on_cboxServer_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
if (index == 2) {
|
||||||
|
ui->cboxPort->setCurrentIndex(1);
|
||||||
|
ui->ckSSL->setChecked(true);
|
||||||
|
} else {
|
||||||
|
ui->cboxPort->setCurrentIndex(0);
|
||||||
|
ui->ckSSL->setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void frmEmailTool::receiveEmailResult(QString result)
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, "提示", result);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef FRMEMAILTOOL_H
|
||||||
|
#define FRMEMAILTOOL_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class frmEmailTool;
|
||||||
|
}
|
||||||
|
|
||||||
|
class frmEmailTool : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit frmEmailTool(QWidget *parent = 0);
|
||||||
|
~frmEmailTool();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::frmEmailTool *ui;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool check();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initForm();
|
||||||
|
void receiveEmailResult(QString result);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_btnSend_clicked();
|
||||||
|
void on_btnSelect_clicked();
|
||||||
|
void on_cboxServer_currentIndexChanged(int index);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRMEMAILTOOL_H
|
|
@ -0,0 +1,223 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>frmEmailTool</class>
|
||||||
|
<widget class="QWidget" name="frmEmailTool">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>764</width>
|
||||||
|
<height>578</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="labSenderAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>用户名:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtSenderAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>feiyangqingyun@126.com</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="labSenderPwd">
|
||||||
|
<property name="text">
|
||||||
|
<string>密码:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLineEdit" name="txtSenderPwd">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLabel" name="labServer">
|
||||||
|
<property name="text">
|
||||||
|
<string>服务器:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="5">
|
||||||
|
<widget class="QComboBox" name="cboxServer">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.163.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.126.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.qq.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smt.sina.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.sohu.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.139.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>smtp.189.com</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QLabel" name="labPort">
|
||||||
|
<property name="text">
|
||||||
|
<string>端口:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="7">
|
||||||
|
<widget class="QComboBox" name="cboxPort">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>25</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>465</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>587</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="8">
|
||||||
|
<widget class="QCheckBox" name="ckSSL">
|
||||||
|
<property name="text">
|
||||||
|
<string>SSL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="9">
|
||||||
|
<widget class="QPushButton" name="btnSend">
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>发送</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="labTitle">
|
||||||
|
<property name="text">
|
||||||
|
<string>标 题:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labFileName">
|
||||||
|
<property name="text">
|
||||||
|
<string>附 件:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="labContent">
|
||||||
|
<property name="text">
|
||||||
|
<string>正 文:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="9">
|
||||||
|
<widget class="QPushButton" name="btnSelect">
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>浏览</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="8">
|
||||||
|
<widget class="QLineEdit" name="txtFileName"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1" colspan="9">
|
||||||
|
<widget class="QTextBrowser" name="txtContent">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'宋体'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">1</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、最短的爱情哲理小说:“</span><span style=" font-size:11pt;">你应该嫁给我啦?</span><span style=" font-family:'Times New Roman'; font-size:11pt;">” “ </span><span style=" font-size:11pt;">不</span><span style=" font-family:'Times New Roman'; font-size:11pt;">” </span><span style=" font-size:11pt;">于是他俩又继续幸福地生活在一起</span><span style=" font-family:'Times New Roman'; font-size:11pt;">!<br /></span><span style=" font-size:11pt;">2</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、近年来中国最精彩的写实小说,全文八个字:</span><span style=" font-family:'Times New Roman'; font-size:16pt; font-weight:600; font-style:italic; color:#ff007f;">此地钱多人傻速来</span><span style=" font-family:'Times New Roman'; font-size:11pt;"> 据说是发自杭州市宝石山下一出租房的汇款单上的简短附言,是该按摩女给家乡妹妹汇 款时随手涂鸦的,令无数专业作家汗颜!<br /></span><span style=" font-size:11pt;">3</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、最短的幽默小说 《夜》 男:疼么?女:恩!男:算了?女:别!</span></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">4</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、最短的荒诞小说:有一个面包走在街上,它觉得自己很饿,就把自己吃了。<br /></span><span style=" font-size:11pt;">5</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短言情小说:他死的那天,孩子出生了。<br /></span><span style=" font-size:11pt;">6</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短武侠小说:</span><span style=" font-family:'Times New Roman'; font-size:11pt; font-weight:600; color:#00aa00;">高手被豆腐砸死了</span><span style=" font-family:'Times New Roman'; font-size:11pt;">。<br /></span><span style=" font-size:11pt;">7</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短科幻小说:最后一个地球人坐在家里,突然响起了敲门声。<br /></span><span style=" font-size:11pt;">8</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短悬疑小说:生,死,生。<br /></span><span style=" font-size:11pt;">9</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短推理小说:他死了,一定曾经活过。 <br />1</span><span style=" font-size:11pt;">0</span><span style=" font-family:'Times New Roman'; font-size:11pt;">、世界最短恐怖小说:惊醒,身边躺着自己的尸体。</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="3">
|
||||||
|
<widget class="QLineEdit" name="txtTitle">
|
||||||
|
<property name="text">
|
||||||
|
<string>测试邮件</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QLabel" name="labReceiverAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>收件人:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5" colspan="5">
|
||||||
|
<widget class="QLineEdit" name="txtReceiverAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>feiyangqingyun@163.com;517216493@qq.com</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
#include "frmemailtool.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QTextCodec>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
a.setFont(QFont("Microsoft Yahei", 9));
|
||||||
|
|
||||||
|
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
|
||||||
|
#if _MSC_VER
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("gbk");
|
||||||
|
#else
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("utf-8");
|
||||||
|
#endif
|
||||||
|
QTextCodec::setCodecForLocale(codec);
|
||||||
|
QTextCodec::setCodecForCStrings(codec);
|
||||||
|
QTextCodec::setCodecForTr(codec);
|
||||||
|
#else
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("utf-8");
|
||||||
|
QTextCodec::setCodecForLocale(codec);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
frmEmailTool w;
|
||||||
|
w.setWindowTitle("邮件发送工具");
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include "emailaddress.h"
|
||||||
|
|
||||||
|
EmailAddress::EmailAddress(const QString &address, const QString &name)
|
||||||
|
{
|
||||||
|
this->address = address;
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailAddress::~EmailAddress()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailAddress::setName(const QString &name)
|
||||||
|
{
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmailAddress::setAddress(const QString &address)
|
||||||
|
{
|
||||||
|
this->address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &EmailAddress::getName() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &EmailAddress::getAddress() const
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef EMAILADDRESS_H
|
||||||
|
#define EMAILADDRESS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class EmailAddress : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
EmailAddress();
|
||||||
|
EmailAddress(const QString &address, const QString &name = "");
|
||||||
|
|
||||||
|
~EmailAddress();
|
||||||
|
|
||||||
|
void setName(const QString &name);
|
||||||
|
void setAddress(const QString &address);
|
||||||
|
|
||||||
|
const QString &getName() const;
|
||||||
|
const QString &getAddress() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString name;
|
||||||
|
QString address;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EMAILADDRESS_H
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include "mimeattachment.h"
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
MimeAttachment::MimeAttachment(QFile *file)
|
||||||
|
: MimeFile(file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeAttachment::~MimeAttachment()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeAttachment::prepare()
|
||||||
|
{
|
||||||
|
this->header += "Content-disposition: attachment\r\n";
|
||||||
|
MimeFile::prepare();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef MIMEATTACHMENT_H
|
||||||
|
#define MIMEATTACHMENT_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include "mimepart.h"
|
||||||
|
#include "mimefile.h"
|
||||||
|
|
||||||
|
class MimeAttachment : public MimeFile
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MimeAttachment(QFile *file);
|
||||||
|
~MimeAttachment();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEATTACHMENT_H
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "mimecontentformatter.h"
|
||||||
|
|
||||||
|
MimeContentFormatter::MimeContentFormatter(int max_length) :
|
||||||
|
max_length(max_length)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString MimeContentFormatter::format(const QString &content, bool quotedPrintable) const
|
||||||
|
{
|
||||||
|
QString out;
|
||||||
|
|
||||||
|
int chars = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < content.length() ; ++i) {
|
||||||
|
chars++;
|
||||||
|
|
||||||
|
if (!quotedPrintable) {
|
||||||
|
if (chars > max_length) {
|
||||||
|
out.append("\r\n");
|
||||||
|
chars = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (content.at(i) == '\n') { // new line
|
||||||
|
out.append(content.at(i));
|
||||||
|
chars = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((chars > max_length - 1)
|
||||||
|
|| ((content.at(i) == '=') && (chars > max_length - 3))) {
|
||||||
|
out.append('=');
|
||||||
|
out.append("\r\n");
|
||||||
|
chars = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(content.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeContentFormatter::setMaxLength(int l)
|
||||||
|
{
|
||||||
|
max_length = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MimeContentFormatter::getMaxLength() const
|
||||||
|
{
|
||||||
|
return max_length;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef MIMECONTENTFORMATTER_H
|
||||||
|
#define MIMECONTENTFORMATTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class MimeContentFormatter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MimeContentFormatter(int max_length = 76);
|
||||||
|
|
||||||
|
void setMaxLength(int l);
|
||||||
|
int getMaxLength() const;
|
||||||
|
|
||||||
|
QString format(const QString &content, bool quotedPrintable = false) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int max_length;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMECONTENTFORMATTER_H
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "mimefile.h"
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
MimeFile::MimeFile(QFile *file)
|
||||||
|
{
|
||||||
|
this->file = file;
|
||||||
|
this->cType = "application/octet-stream";
|
||||||
|
this->cName = QFileInfo(*file).fileName();
|
||||||
|
this->cEncoding = Base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeFile::~MimeFile()
|
||||||
|
{
|
||||||
|
delete file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeFile::prepare()
|
||||||
|
{
|
||||||
|
file->open(QIODevice::ReadOnly);
|
||||||
|
this->content = file->readAll();
|
||||||
|
file->close();
|
||||||
|
MimePart::prepare();
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef MIMEFILE_H
|
||||||
|
#define MIMEFILE_H
|
||||||
|
|
||||||
|
#include "mimepart.h"
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
class MimeFile : public MimePart
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
MimeFile(QFile *f);
|
||||||
|
~MimeFile();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QFile *file;
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEFILE_H
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "mimehtml.h"
|
||||||
|
|
||||||
|
MimeHtml::MimeHtml(const QString &html) : MimeText(html)
|
||||||
|
{
|
||||||
|
this->cType = "text/html";
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeHtml::~MimeHtml() {}
|
||||||
|
|
||||||
|
void MimeHtml::setHtml(const QString &html)
|
||||||
|
{
|
||||||
|
this->text = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimeHtml::getHtml() const
|
||||||
|
{
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeHtml::prepare()
|
||||||
|
{
|
||||||
|
MimeText::prepare();
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef MIMEHTML_H
|
||||||
|
#define MIMEHTML_H
|
||||||
|
|
||||||
|
#include "mimetext.h"
|
||||||
|
|
||||||
|
class MimeHtml : public MimeText
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MimeHtml(const QString &html = "");
|
||||||
|
~MimeHtml();
|
||||||
|
|
||||||
|
void setHtml(const QString &html);
|
||||||
|
const QString &getHtml() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEHTML_H
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "mimeinlinefile.h"
|
||||||
|
|
||||||
|
MimeInlineFile::MimeInlineFile(QFile *f)
|
||||||
|
: MimeFile(f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeInlineFile::~MimeInlineFile()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void MimeInlineFile::prepare()
|
||||||
|
{
|
||||||
|
this->header += "Content-Disposition: inline\r\n";
|
||||||
|
MimeFile::prepare();
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef MIMEINLINEFILE_H
|
||||||
|
#define MIMEINLINEFILE_H
|
||||||
|
|
||||||
|
#include "mimefile.h"
|
||||||
|
|
||||||
|
class MimeInlineFile : public MimeFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MimeInlineFile(QFile *f);
|
||||||
|
~MimeInlineFile();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEINLINEFILE_H
|
|
@ -0,0 +1,222 @@
|
||||||
|
#include "mimemessage.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include "quotedprintable.h"
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
MimeMessage::MimeMessage(bool createAutoMimeContent) :
|
||||||
|
hEncoding(MimePart::_8Bit)
|
||||||
|
{
|
||||||
|
if (createAutoMimeContent) {
|
||||||
|
this->content = new MimeMultiPart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeMessage::~MimeMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MimePart &MimeMessage::getContent()
|
||||||
|
{
|
||||||
|
return *content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::setContent(MimePart *content)
|
||||||
|
{
|
||||||
|
this->content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::setSender(EmailAddress *e)
|
||||||
|
{
|
||||||
|
this->sender = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case To:
|
||||||
|
recipientsTo << rcpt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cc:
|
||||||
|
recipientsCc << rcpt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Bcc:
|
||||||
|
recipientsBcc << rcpt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::addTo(EmailAddress *rcpt)
|
||||||
|
{
|
||||||
|
this->recipientsTo << rcpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::addCc(EmailAddress *rcpt)
|
||||||
|
{
|
||||||
|
this->recipientsCc << rcpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::addBcc(EmailAddress *rcpt)
|
||||||
|
{
|
||||||
|
this->recipientsBcc << rcpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::setSubject(const QString &subject)
|
||||||
|
{
|
||||||
|
this->subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::addPart(MimePart *part)
|
||||||
|
{
|
||||||
|
if (typeid(*content) == typeid(MimeMultiPart)) {
|
||||||
|
((MimeMultiPart *) content)->addPart(part);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc)
|
||||||
|
{
|
||||||
|
this->hEncoding = hEnc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EmailAddress &MimeMessage::getSender() const
|
||||||
|
{
|
||||||
|
return *sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<EmailAddress *> &MimeMessage::getRecipients(RecipientType type) const
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
case To:
|
||||||
|
return recipientsTo;
|
||||||
|
|
||||||
|
case Cc:
|
||||||
|
return recipientsCc;
|
||||||
|
|
||||||
|
case Bcc:
|
||||||
|
return recipientsBcc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimeMessage::getSubject() const
|
||||||
|
{
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<MimePart *> &MimeMessage::getParts() const
|
||||||
|
{
|
||||||
|
if (typeid(*content) == typeid(MimeMultiPart)) {
|
||||||
|
return ((MimeMultiPart *) content)->getParts();
|
||||||
|
} else {
|
||||||
|
QList<MimePart *> *res = new QList<MimePart *>();
|
||||||
|
res->append(content);
|
||||||
|
return *res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MimeMessage::toString()
|
||||||
|
{
|
||||||
|
QString mime;
|
||||||
|
|
||||||
|
mime = "From:";
|
||||||
|
|
||||||
|
if (sender->getName() != "") {
|
||||||
|
switch (hEncoding) {
|
||||||
|
case MimePart::Base64:
|
||||||
|
mime += " =?utf-8?B?" + QByteArray().append(sender->getName()).toBase64() + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MimePart::QuotedPrintable:
|
||||||
|
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(sender->getName())).replace(' ', "_").replace(':', "=3A") + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mime += " " + sender->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += " <" + sender->getAddress() + ">\r\n";
|
||||||
|
|
||||||
|
mime += "To:";
|
||||||
|
QList<EmailAddress *>::iterator it;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
mime += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*it)->getName() != "") {
|
||||||
|
switch (hEncoding) {
|
||||||
|
case MimePart::Base64:
|
||||||
|
mime += " =?utf-8?B?" + QByteArray().append((*it)->getName()).toBase64() + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MimePart::QuotedPrintable:
|
||||||
|
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append((*it)->getName())).replace(' ', "_").replace(':', "=3A") + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mime += " " + (*it)->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += " <" + (*it)->getAddress() + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += "\r\n";
|
||||||
|
|
||||||
|
if (recipientsCc.size() != 0) {
|
||||||
|
mime += "Cc:";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
mime += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*it)->getName() != "") {
|
||||||
|
switch (hEncoding) {
|
||||||
|
case MimePart::Base64:
|
||||||
|
mime += " =?utf-8?B?" + QByteArray().append((*it)->getName()).toBase64() + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MimePart::QuotedPrintable:
|
||||||
|
mime += " =?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append((*it)->getName())).replace(' ', "_").replace(':', "=3A") + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mime += " " + (*it)->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += " <" + (*it)->getAddress() + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipientsCc.size() != 0) {
|
||||||
|
mime += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += "Subject: ";
|
||||||
|
|
||||||
|
switch (hEncoding) {
|
||||||
|
case MimePart::Base64:
|
||||||
|
mime += "=?utf-8?B?" + QByteArray().append(subject).toBase64() + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MimePart::QuotedPrintable:
|
||||||
|
mime += "=?utf-8?Q?" + QuotedPrintable::encode(QByteArray().append(subject)).replace(' ', "_").replace(':', "=3A") + "?=";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mime += subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
mime += "\r\n";
|
||||||
|
mime += "MIME-Version: 1.0\r\n";
|
||||||
|
|
||||||
|
mime += content->toString();
|
||||||
|
return mime;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef MIMEMESSAGE_H
|
||||||
|
#define MIMEMESSAGE_H
|
||||||
|
|
||||||
|
#include "mimepart.h"
|
||||||
|
#include "mimemultipart.h"
|
||||||
|
#include "emailaddress.h"
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class MimeMessage : public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum RecipientType {
|
||||||
|
To, // primary
|
||||||
|
Cc, // carbon copy
|
||||||
|
Bcc // blind carbon copy
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MimeMessage(bool createAutoMimeConent = true);
|
||||||
|
~MimeMessage();
|
||||||
|
|
||||||
|
void setSender(EmailAddress *e);
|
||||||
|
void addRecipient(EmailAddress *rcpt, RecipientType type = To);
|
||||||
|
void addTo(EmailAddress *rcpt);
|
||||||
|
void addCc(EmailAddress *rcpt);
|
||||||
|
void addBcc(EmailAddress *rcpt);
|
||||||
|
void setSubject(const QString &subject);
|
||||||
|
void addPart(MimePart *part);
|
||||||
|
|
||||||
|
void setHeaderEncoding(MimePart::Encoding);
|
||||||
|
|
||||||
|
const EmailAddress &getSender() const;
|
||||||
|
const QList<EmailAddress *> &getRecipients(RecipientType type = To) const;
|
||||||
|
const QString &getSubject() const;
|
||||||
|
const QList<MimePart *> &getParts() const;
|
||||||
|
|
||||||
|
MimePart &getContent();
|
||||||
|
void setContent(MimePart *content);
|
||||||
|
|
||||||
|
virtual QString toString();
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EmailAddress *sender;
|
||||||
|
QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc;
|
||||||
|
QString subject;
|
||||||
|
MimePart *content;
|
||||||
|
|
||||||
|
MimePart::Encoding hEncoding;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEMESSAGE_H
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "mimemultipart.h"
|
||||||
|
#include <QTime>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
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(qrand()));
|
||||||
|
cBoundary = md5.result().toHex();
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeMultiPart::~MimeMultiPart()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMultiPart::addPart(MimePart *part)
|
||||||
|
{
|
||||||
|
parts.append(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<MimePart *> &MimeMultiPart::getParts() const
|
||||||
|
{
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMultiPart::prepare()
|
||||||
|
{
|
||||||
|
QList<MimePart *>::iterator it;
|
||||||
|
|
||||||
|
content = "";
|
||||||
|
|
||||||
|
for (it = parts.begin(); it != parts.end(); it++) {
|
||||||
|
content += "--" + cBoundary + "\r\n";
|
||||||
|
(*it)->prepare();
|
||||||
|
content += (*it)->toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
content += "--" + cBoundary + "--\r\n";
|
||||||
|
|
||||||
|
MimePart::prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeMultiPart::setMimeType(const MultiPartType type)
|
||||||
|
{
|
||||||
|
this->type = type;
|
||||||
|
this->cType = MULTI_PART_NAMES[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef MIMEMULTIPART_H
|
||||||
|
#define MIMEMULTIPART_H
|
||||||
|
|
||||||
|
#include "mimepart.h"
|
||||||
|
|
||||||
|
class MimeMultiPart : public MimePart
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum MultiPartType {
|
||||||
|
Mixed = 0, // RFC 2046, section 5.1.3
|
||||||
|
Digest = 1, // RFC 2046, section 5.1.5
|
||||||
|
Alternative = 2, // RFC 2046, section 5.1.4
|
||||||
|
Related = 3, // RFC 2387
|
||||||
|
Report = 4, // RFC 6522
|
||||||
|
Signed = 5, // RFC 1847, section 2.1
|
||||||
|
Encrypted = 6 // RFC 1847, section 2.2
|
||||||
|
};
|
||||||
|
|
||||||
|
MimeMultiPart(const MultiPartType type = Related);
|
||||||
|
~MimeMultiPart();
|
||||||
|
|
||||||
|
void setMimeType(const MultiPartType type);
|
||||||
|
MultiPartType getMimeType() const;
|
||||||
|
|
||||||
|
const QList<MimePart *> &getParts() const;
|
||||||
|
|
||||||
|
void addPart(MimePart *part);
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QList<MimePart *> parts;
|
||||||
|
MultiPartType type;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEMULTIPART_H
|
|
@ -0,0 +1,171 @@
|
||||||
|
#include "mimepart.h"
|
||||||
|
#include "quotedprintable.h"
|
||||||
|
|
||||||
|
MimePart::MimePart()
|
||||||
|
{
|
||||||
|
cEncoding = _7Bit;
|
||||||
|
prepared = false;
|
||||||
|
cBoundary = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
MimePart::~MimePart()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setContent(const QByteArray &content)
|
||||||
|
{
|
||||||
|
this->content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setHeader(const QString &header)
|
||||||
|
{
|
||||||
|
this->header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::addHeaderLine(const QString &line)
|
||||||
|
{
|
||||||
|
this->header += line + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimePart::getHeader() const
|
||||||
|
{
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray &MimePart::getContent() const
|
||||||
|
{
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setContentId(const QString &cId)
|
||||||
|
{
|
||||||
|
this->cId = cId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimePart::getContentId() const
|
||||||
|
{
|
||||||
|
return this->cId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setContentName(const QString &cName)
|
||||||
|
{
|
||||||
|
this->cName = cName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimePart::getContentName() const
|
||||||
|
{
|
||||||
|
return this->cName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setContentType(const QString &cType)
|
||||||
|
{
|
||||||
|
this->cType = cType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimePart::getContentType() const
|
||||||
|
{
|
||||||
|
return this->cType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setCharset(const QString &charset)
|
||||||
|
{
|
||||||
|
this->cCharset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimePart::getCharset() const
|
||||||
|
{
|
||||||
|
return this->cCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::setEncoding(Encoding enc)
|
||||||
|
{
|
||||||
|
this->cEncoding = enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
MimePart::Encoding MimePart::getEncoding() const
|
||||||
|
{
|
||||||
|
return this->cEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeContentFormatter &MimePart::getContentFormatter()
|
||||||
|
{
|
||||||
|
return this->formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MimePart::toString()
|
||||||
|
{
|
||||||
|
if (!prepared) {
|
||||||
|
prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimePart::prepare()
|
||||||
|
{
|
||||||
|
mimeString = QString();
|
||||||
|
|
||||||
|
mimeString.append("Content-Type: ").append(cType);
|
||||||
|
|
||||||
|
if (cName != "") {
|
||||||
|
mimeString.append("; name=\"").append(cName).append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cCharset != "") {
|
||||||
|
mimeString.append("; charset=").append(cCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cBoundary != "") {
|
||||||
|
mimeString.append("; boundary=").append(cBoundary);
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeString.append("\r\n");
|
||||||
|
|
||||||
|
mimeString.append("Content-Transfer-Encoding: ");
|
||||||
|
|
||||||
|
switch (cEncoding) {
|
||||||
|
case _7Bit:
|
||||||
|
mimeString.append("7bit\r\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _8Bit:
|
||||||
|
mimeString.append("8bit\r\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Base64:
|
||||||
|
mimeString.append("base64\r\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuotedPrintable:
|
||||||
|
mimeString.append("quoted-printable\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cId != 0) {
|
||||||
|
mimeString.append("Content-ID: <").append(cId).append(">\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeString.append(header).append("\r\n");
|
||||||
|
|
||||||
|
switch (cEncoding) {
|
||||||
|
case _7Bit:
|
||||||
|
mimeString.append(QString(content).toLatin1());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _8Bit:
|
||||||
|
mimeString.append(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Base64:
|
||||||
|
mimeString.append(formatter.format(content.toBase64()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QuotedPrintable:
|
||||||
|
mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeString.append("\r\n");
|
||||||
|
prepared = true;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef MIMEPART_H
|
||||||
|
#define MIMEPART_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "mimecontentformatter.h"
|
||||||
|
|
||||||
|
class MimePart : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Encoding {
|
||||||
|
_7Bit,
|
||||||
|
_8Bit,
|
||||||
|
Base64,
|
||||||
|
QuotedPrintable
|
||||||
|
};
|
||||||
|
|
||||||
|
MimePart();
|
||||||
|
~MimePart();
|
||||||
|
|
||||||
|
const QString &getHeader() const;
|
||||||
|
const QByteArray &getContent() const;
|
||||||
|
|
||||||
|
void setContent(const QByteArray &content);
|
||||||
|
void setHeader(const QString &header);
|
||||||
|
|
||||||
|
void addHeaderLine(const QString &line);
|
||||||
|
|
||||||
|
void setContentId(const QString &cId);
|
||||||
|
const QString &getContentId() const;
|
||||||
|
|
||||||
|
void setContentName(const QString &cName);
|
||||||
|
const QString &getContentName() const;
|
||||||
|
|
||||||
|
void setContentType(const QString &cType);
|
||||||
|
const QString &getContentType() const;
|
||||||
|
|
||||||
|
void setCharset(const QString &charset);
|
||||||
|
const QString &getCharset() const;
|
||||||
|
|
||||||
|
void setEncoding(Encoding enc);
|
||||||
|
Encoding getEncoding() const;
|
||||||
|
|
||||||
|
MimeContentFormatter &getContentFormatter();
|
||||||
|
|
||||||
|
virtual QString toString();
|
||||||
|
virtual void prepare();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString header;
|
||||||
|
QByteArray content;
|
||||||
|
|
||||||
|
QString cId;
|
||||||
|
QString cName;
|
||||||
|
QString cType;
|
||||||
|
QString cCharset;
|
||||||
|
QString cBoundary;
|
||||||
|
Encoding cEncoding;
|
||||||
|
|
||||||
|
QString mimeString;
|
||||||
|
bool prepared;
|
||||||
|
|
||||||
|
MimeContentFormatter formatter;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMEPART_H
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "mimetext.h"
|
||||||
|
|
||||||
|
MimeText::MimeText(const QString &txt)
|
||||||
|
{
|
||||||
|
this->text = txt;
|
||||||
|
this->cType = "text/plain";
|
||||||
|
this->cCharset = "utf-8";
|
||||||
|
this->cEncoding = _8Bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MimeText::~MimeText() { }
|
||||||
|
|
||||||
|
void MimeText::setText(const QString &text)
|
||||||
|
{
|
||||||
|
this->text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &MimeText::getText() const
|
||||||
|
{
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MimeText::prepare()
|
||||||
|
{
|
||||||
|
this->content.clear();
|
||||||
|
this->content.append(text);
|
||||||
|
MimePart::prepare();
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef MIMETEXT_H
|
||||||
|
#define MIMETEXT_H
|
||||||
|
|
||||||
|
#include "mimepart.h"
|
||||||
|
|
||||||
|
class MimeText : public MimePart
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MimeText(const QString &text = "");
|
||||||
|
~MimeText();
|
||||||
|
|
||||||
|
void setText(const QString &text);
|
||||||
|
const QString &getText() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString text;
|
||||||
|
void prepare();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIMETEXT_H
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "quotedprintable.h"
|
||||||
|
|
||||||
|
QString &QuotedPrintable::encode(const QByteArray &input)
|
||||||
|
{
|
||||||
|
QString *output = new QString();
|
||||||
|
|
||||||
|
char byte;
|
||||||
|
const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
|
for (int i = 0; i < input.length() ; ++i) {
|
||||||
|
byte = input.at(i);
|
||||||
|
|
||||||
|
if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) {
|
||||||
|
output->append(byte);
|
||||||
|
} else {
|
||||||
|
output->append('=');
|
||||||
|
output->append(hex[((byte >> 4) & 0x0F)]);
|
||||||
|
output->append(hex[(byte & 0x0F)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QByteArray &QuotedPrintable::decode(const QString &input)
|
||||||
|
{
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F
|
||||||
|
const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
|
||||||
|
|
||||||
|
QByteArray *output = new QByteArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < input.length(); ++i) {
|
||||||
|
if (input.at(i).toLatin1() == '=') {
|
||||||
|
int index = ++i;
|
||||||
|
output->append((hexVal[input.at(index).toLatin1() - '0'] << 4) + hexVal[input.at(++i).toLatin1() - '0']);
|
||||||
|
} else {
|
||||||
|
output->append(input.at(i).toLatin1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *output;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef QUOTEDPRINTABLE_H
|
||||||
|
#define QUOTEDPRINTABLE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class QuotedPrintable : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
static QString &encode(const QByteArray &input);
|
||||||
|
static QByteArray &decode(const QString &input);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QuotedPrintable();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUOTEDPRINTABLE_H
|
|
@ -0,0 +1,30 @@
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/emailaddress.h \
|
||||||
|
$$PWD/mimeattachment.h \
|
||||||
|
$$PWD/mimecontentformatter.h \
|
||||||
|
$$PWD/mimefile.h \
|
||||||
|
$$PWD/mimehtml.h \
|
||||||
|
$$PWD/mimeinlinefile.h \
|
||||||
|
$$PWD/mimemessage.h \
|
||||||
|
$$PWD/mimemultipart.h \
|
||||||
|
$$PWD/mimepart.h \
|
||||||
|
$$PWD/mimetext.h \
|
||||||
|
$$PWD/quotedprintable.h \
|
||||||
|
$$PWD/smtpclient.h \
|
||||||
|
$$PWD/smtpmime.h \
|
||||||
|
$$PWD/sendemailthread.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/emailaddress.cpp \
|
||||||
|
$$PWD/mimeattachment.cpp \
|
||||||
|
$$PWD/mimecontentformatter.cpp \
|
||||||
|
$$PWD/mimefile.cpp \
|
||||||
|
$$PWD/mimehtml.cpp \
|
||||||
|
$$PWD/mimeinlinefile.cpp \
|
||||||
|
$$PWD/mimemessage.cpp \
|
||||||
|
$$PWD/mimemultipart.cpp \
|
||||||
|
$$PWD/mimepart.cpp \
|
||||||
|
$$PWD/mimetext.cpp \
|
||||||
|
$$PWD/quotedprintable.cpp \
|
||||||
|
$$PWD/smtpclient.cpp \
|
||||||
|
$$PWD/sendemailthread.cpp
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include "sendemailthread.h"
|
||||||
|
#include "sendemail/smtpmime.h"
|
||||||
|
|
||||||
|
QScopedPointer<SendEmailThread> SendEmailThread::self;
|
||||||
|
SendEmailThread *SendEmailThread::Instance()
|
||||||
|
{
|
||||||
|
if (self.isNull()) {
|
||||||
|
static QMutex mutex;
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (self.isNull()) {
|
||||||
|
self.reset(new SendEmailThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendEmailThread::SendEmailThread(QObject *parent) : QThread(parent)
|
||||||
|
{
|
||||||
|
stopped = false;
|
||||||
|
emialTitle = "邮件标题";
|
||||||
|
sendEmailAddr = "feiyangqingyun@126.com";
|
||||||
|
sendEmailPwd = "123456789";
|
||||||
|
receiveEmailAddr = "feiyangqingyun@163.com;517216493@qq.com";
|
||||||
|
contents.clear();
|
||||||
|
fileNames.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendEmailThread::~SendEmailThread()
|
||||||
|
{
|
||||||
|
this->stop();
|
||||||
|
this->wait(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::run()
|
||||||
|
{
|
||||||
|
while (!stopped) {
|
||||||
|
int count = contents.count();
|
||||||
|
if (count > 0) {
|
||||||
|
mutex.lock();
|
||||||
|
QString content = contents.takeFirst();
|
||||||
|
QString fileName = fileNames.takeFirst();
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
QString result;
|
||||||
|
QStringList list = sendEmailAddr.split("@");
|
||||||
|
QString tempSMTP = list.at(1).split(".").at(0);
|
||||||
|
int tempPort = 25;
|
||||||
|
|
||||||
|
//QQ邮箱端口号为465,必须启用SSL协议.
|
||||||
|
if (tempSMTP.toUpper() == "QQ") {
|
||||||
|
tempPort = 465;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmtpClient smtp(QString("smtp.%1.com").arg(tempSMTP), tempPort, tempPort == 25 ? SmtpClient::TcpConnection : SmtpClient::SslConnection);
|
||||||
|
smtp.setUser(sendEmailAddr);
|
||||||
|
smtp.setPassword(sendEmailPwd);
|
||||||
|
|
||||||
|
//构建邮件主题,包含发件人收件人附件等.
|
||||||
|
MimeMessage message;
|
||||||
|
message.setSender(new EmailAddress(sendEmailAddr));
|
||||||
|
|
||||||
|
//逐个添加收件人
|
||||||
|
QStringList receiver = receiveEmailAddr.split(';');
|
||||||
|
for (int i = 0; i < receiver.size(); i++) {
|
||||||
|
message.addRecipient(new EmailAddress(receiver.at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//构建邮件标题
|
||||||
|
message.setSubject(emialTitle);
|
||||||
|
|
||||||
|
//构建邮件正文
|
||||||
|
MimeHtml text;
|
||||||
|
text.setHtml(content);
|
||||||
|
message.addPart(&text);
|
||||||
|
|
||||||
|
//构建附件-报警图像
|
||||||
|
if (fileName.length() > 0) {
|
||||||
|
QStringList attas = fileName.split(";");
|
||||||
|
foreach (QString tempAtta, attas) {
|
||||||
|
QFile *file = new QFile(tempAtta);
|
||||||
|
if (file->exists()) {
|
||||||
|
message.addPart(new MimeAttachment(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!smtp.connectToHost()) {
|
||||||
|
result = "邮件服务器连接失败";
|
||||||
|
} else {
|
||||||
|
if (!smtp.login()) {
|
||||||
|
result = "邮件用户登录失败";
|
||||||
|
} else {
|
||||||
|
if (!smtp.sendMail(message)) {
|
||||||
|
result = "邮件发送失败";
|
||||||
|
} else {
|
||||||
|
result = "邮件发送成功";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smtp.quit();
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
emit receiveEmailResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::stop()
|
||||||
|
{
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::setEmialTitle(const QString &emailTitle)
|
||||||
|
{
|
||||||
|
this->emialTitle = emailTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::setSendEmailAddr(const QString &sendEmailAddr)
|
||||||
|
{
|
||||||
|
this->sendEmailAddr = sendEmailAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::setSendEmailPwd(const QString &sendEmailPwd)
|
||||||
|
{
|
||||||
|
this->sendEmailPwd = sendEmailPwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::setReceiveEmailAddr(const QString &receiveEmailAddr)
|
||||||
|
{
|
||||||
|
this->receiveEmailAddr = receiveEmailAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEmailThread::append(const QString &content, const QString &fileName)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
contents.append(content);
|
||||||
|
fileNames.append(fileName);
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef SENDEMAILTHREAD_H
|
||||||
|
#define SENDEMAILTHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class SendEmailThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static SendEmailThread *Instance();
|
||||||
|
explicit SendEmailThread(QObject *parent = 0);
|
||||||
|
~SendEmailThread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QScopedPointer<SendEmailThread> self;
|
||||||
|
QMutex mutex;
|
||||||
|
volatile bool stopped;
|
||||||
|
|
||||||
|
QString emialTitle; //邮件标题
|
||||||
|
QString sendEmailAddr; //发件人邮箱
|
||||||
|
QString sendEmailPwd; //发件人密码
|
||||||
|
QString receiveEmailAddr; //收件人邮箱,可多个中间;隔开
|
||||||
|
QStringList contents; //正文内容
|
||||||
|
QStringList fileNames; //附件
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void receiveEmailResult(const QString &result);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void stop();
|
||||||
|
void setEmialTitle(const QString &emailTitle);
|
||||||
|
void setSendEmailAddr(const QString &sendEmailAddr);
|
||||||
|
void setSendEmailPwd(const QString &sendEmailPwd);
|
||||||
|
void setReceiveEmailAddr(const QString &receiveEmailAddr);
|
||||||
|
void append(const QString &content, const QString &fileName);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SENDEMAILTHREAD_H
|
|
@ -0,0 +1,390 @@
|
||||||
|
#include "smtpclient.h"
|
||||||
|
|
||||||
|
SmtpClient::SmtpClient(const QString &host, int port, ConnectionType connectionType) :
|
||||||
|
name("localhost"),
|
||||||
|
authMethod(AuthPlain),
|
||||||
|
connectionTimeout(5000),
|
||||||
|
responseTimeout(5000)
|
||||||
|
{
|
||||||
|
setConnectionType(connectionType);
|
||||||
|
|
||||||
|
this->host = host;
|
||||||
|
this->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmtpClient::~SmtpClient() {}
|
||||||
|
|
||||||
|
void SmtpClient::setUser(const QString &user)
|
||||||
|
{
|
||||||
|
this->user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setPassword(const QString &password)
|
||||||
|
{
|
||||||
|
this->password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setAuthMethod(AuthMethod method)
|
||||||
|
{
|
||||||
|
this->authMethod = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setHost(QString &host)
|
||||||
|
{
|
||||||
|
this->host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setPort(int port)
|
||||||
|
{
|
||||||
|
this->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setConnectionType(ConnectionType ct)
|
||||||
|
{
|
||||||
|
this->connectionType = ct;
|
||||||
|
|
||||||
|
switch (connectionType) {
|
||||||
|
case TcpConnection:
|
||||||
|
socket = new QTcpSocket(this);
|
||||||
|
break;
|
||||||
|
#ifdef ssl
|
||||||
|
case SslConnection:
|
||||||
|
case TlsConnection:
|
||||||
|
socket = new QSslSocket(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &SmtpClient::getHost() const
|
||||||
|
{
|
||||||
|
return this->host;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &SmtpClient::getUser() const
|
||||||
|
{
|
||||||
|
return this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &SmtpClient::getPassword() const
|
||||||
|
{
|
||||||
|
return this->password;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmtpClient::AuthMethod SmtpClient::getAuthMethod() const
|
||||||
|
{
|
||||||
|
return this->authMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmtpClient::getPort() const
|
||||||
|
{
|
||||||
|
return this->port;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmtpClient::ConnectionType SmtpClient::getConnectionType() const
|
||||||
|
{
|
||||||
|
return connectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &SmtpClient::getName() const
|
||||||
|
{
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setName(const QString &name)
|
||||||
|
{
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &SmtpClient::getResponseText() const
|
||||||
|
{
|
||||||
|
return responseText;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmtpClient::getResponseCode() const
|
||||||
|
{
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTcpSocket *SmtpClient::getSocket()
|
||||||
|
{
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmtpClient::getConnectionTimeout() const
|
||||||
|
{
|
||||||
|
return connectionTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setConnectionTimeout(int msec)
|
||||||
|
{
|
||||||
|
connectionTimeout = msec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmtpClient::getResponseTimeout() const
|
||||||
|
{
|
||||||
|
return responseTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::setResponseTimeout(int msec)
|
||||||
|
{
|
||||||
|
responseTimeout = msec;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmtpClient::connectToHost()
|
||||||
|
{
|
||||||
|
switch (connectionType) {
|
||||||
|
case TlsConnection:
|
||||||
|
case TcpConnection:
|
||||||
|
socket->connectToHost(host, port);
|
||||||
|
break;
|
||||||
|
#ifdef ssl
|
||||||
|
case SslConnection:
|
||||||
|
((QSslSocket *) socket)->connectToHostEncrypted(host, port);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!socket->waitForConnected(connectionTimeout)) {
|
||||||
|
emit smtpError(ConnectionTimeoutError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wait for the server's response
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// If the response code is not 220 (Service ready)
|
||||||
|
// means that is something wrong with the server
|
||||||
|
if (responseCode != 220) {
|
||||||
|
emit smtpError(ServerError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a EHLO/HELO message to the server
|
||||||
|
// The client's first command must be EHLO/HELO
|
||||||
|
sendMessage("EHLO " + name);
|
||||||
|
|
||||||
|
// Wait for the server's response
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// The response code needs to be 250.
|
||||||
|
if (responseCode != 250) {
|
||||||
|
emit smtpError(ServerError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionType == TlsConnection) {
|
||||||
|
// send a request to start TLS handshake
|
||||||
|
sendMessage("STARTTLS");
|
||||||
|
|
||||||
|
// Wait for the server's response
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// The response code needs to be 220.
|
||||||
|
if (responseCode != 220) {
|
||||||
|
emit smtpError(ServerError);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
#ifdef ssl
|
||||||
|
((QSslSocket *) socket)->startClientEncryption();
|
||||||
|
if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) {
|
||||||
|
qDebug() << ((QSslSocket *) socket)->errorString();
|
||||||
|
emit smtpError(ConnectionTimeoutError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Send ELHO one more time
|
||||||
|
sendMessage("EHLO " + name);
|
||||||
|
|
||||||
|
// Wait for the server's response
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// The response code needs to be 250.
|
||||||
|
if (responseCode != 250) {
|
||||||
|
emit smtpError(ServerError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ResponseTimeoutException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmtpClient::login()
|
||||||
|
{
|
||||||
|
return login(user, password, authMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmtpClient::login(const QString &user, const QString &password, AuthMethod method)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (method == AuthPlain) {
|
||||||
|
// Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
|
||||||
|
sendMessage("AUTH PLAIN " + QByteArray().append((char) 0).append(user).append((char) 0).append(password).toBase64());
|
||||||
|
|
||||||
|
// Wait for the server's response
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// If the response is not 235 then the authentication was faild
|
||||||
|
if (responseCode != 235) {
|
||||||
|
emit smtpError(AuthenticationFailedError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (method == AuthLogin) {
|
||||||
|
// Sending command: AUTH LOGIN
|
||||||
|
sendMessage("AUTH LOGIN");
|
||||||
|
|
||||||
|
// Wait for 334 response code
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 334) {
|
||||||
|
emit smtpError(AuthenticationFailedError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the username in base64
|
||||||
|
sendMessage(QByteArray().append(user).toBase64());
|
||||||
|
|
||||||
|
// Wait for 334
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 334) {
|
||||||
|
emit smtpError(AuthenticationFailedError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the password in base64
|
||||||
|
sendMessage(QByteArray().append(password).toBase64());
|
||||||
|
|
||||||
|
// Wait for the server's responce
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
// If the response is not 235 then the authentication was faild
|
||||||
|
if (responseCode != 235) {
|
||||||
|
emit smtpError(AuthenticationFailedError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ResponseTimeoutException e) {
|
||||||
|
// Responce Timeout exceeded
|
||||||
|
emit smtpError(AuthenticationFailedError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmtpClient::sendMail(MimeMessage &email)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Send the MAIL command with the sender
|
||||||
|
sendMessage("MAIL FROM: <" + email.getSender().getAddress() + ">");
|
||||||
|
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 250) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send RCPT command for each recipient
|
||||||
|
QList<EmailAddress *>::const_iterator it, itEnd;
|
||||||
|
|
||||||
|
// To (primary recipients)
|
||||||
|
for (it = email.getRecipients().begin(), itEnd = email.getRecipients().end();
|
||||||
|
it != itEnd; ++it) {
|
||||||
|
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 250) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cc (carbon copy)
|
||||||
|
for (it = email.getRecipients(MimeMessage::Cc).begin(), itEnd = email.getRecipients(MimeMessage::Cc).end();
|
||||||
|
it != itEnd; ++it) {
|
||||||
|
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 250) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bcc (blind carbon copy)
|
||||||
|
for (it = email.getRecipients(MimeMessage::Bcc).begin(), itEnd = email.getRecipients(MimeMessage::Bcc).end();
|
||||||
|
it != itEnd; ++it) {
|
||||||
|
sendMessage("RCPT TO: <" + (*it)->getAddress() + ">");
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 250) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send DATA command
|
||||||
|
sendMessage("DATA");
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 354) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage(email.toString());
|
||||||
|
|
||||||
|
// Send \r\n.\r\n to end the mail data
|
||||||
|
sendMessage(".");
|
||||||
|
|
||||||
|
waitForResponse();
|
||||||
|
|
||||||
|
if (responseCode != 250) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (ResponseTimeoutException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::quit()
|
||||||
|
{
|
||||||
|
sendMessage("QUIT");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::waitForResponse() throw (ResponseTimeoutException)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
if (!socket->waitForReadyRead(responseTimeout)) {
|
||||||
|
emit smtpError(ResponseTimeoutError);
|
||||||
|
throw ResponseTimeoutException();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (socket->canReadLine()) {
|
||||||
|
// Save the server's response
|
||||||
|
responseText = socket->readLine();
|
||||||
|
|
||||||
|
// Extract the respose code from the server's responce (first 3 digits)
|
||||||
|
responseCode = responseText.left(3).toInt();
|
||||||
|
|
||||||
|
if (responseCode / 100 == 4) {
|
||||||
|
emit smtpError(ServerError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCode / 100 == 5) {
|
||||||
|
emit smtpError(ClientError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseText.at(3) == ' ') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmtpClient::sendMessage(const QString &text)
|
||||||
|
{
|
||||||
|
socket->write(text.toUtf8() + "\r\n");
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
#ifndef SMTPCLIENT_H
|
||||||
|
#define SMTPCLIENT_H
|
||||||
|
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtNetwork>
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
|
||||||
|
#include <QtWidgets>
|
||||||
|
#endif
|
||||||
|
#include "mimemessage.h"
|
||||||
|
|
||||||
|
class SmtpClient : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum AuthMethod {
|
||||||
|
AuthPlain,
|
||||||
|
AuthLogin
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SmtpError {
|
||||||
|
ConnectionTimeoutError,
|
||||||
|
ResponseTimeoutError,
|
||||||
|
AuthenticationFailedError,
|
||||||
|
ServerError, // 4xx smtp error
|
||||||
|
ClientError // 5xx smtp error
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ConnectionType {
|
||||||
|
TcpConnection,
|
||||||
|
SslConnection,
|
||||||
|
TlsConnection // STARTTLS
|
||||||
|
};
|
||||||
|
|
||||||
|
SmtpClient(const QString &host = "locahost", int port = 25, ConnectionType ct = TcpConnection);
|
||||||
|
|
||||||
|
~SmtpClient();
|
||||||
|
|
||||||
|
const QString &getHost() const;
|
||||||
|
void setHost(QString &host);
|
||||||
|
|
||||||
|
int getPort() const;
|
||||||
|
void setPort(int port);
|
||||||
|
|
||||||
|
const QString &getName() const;
|
||||||
|
void setName(const QString &name);
|
||||||
|
|
||||||
|
ConnectionType getConnectionType() const;
|
||||||
|
void setConnectionType(ConnectionType ct);
|
||||||
|
|
||||||
|
const QString &getUser() const;
|
||||||
|
void setUser(const QString &host);
|
||||||
|
|
||||||
|
const QString &getPassword() const;
|
||||||
|
void setPassword(const QString &password);
|
||||||
|
|
||||||
|
SmtpClient::AuthMethod getAuthMethod() const;
|
||||||
|
void setAuthMethod(AuthMethod method);
|
||||||
|
|
||||||
|
const QString &getResponseText() const;
|
||||||
|
int getResponseCode() const;
|
||||||
|
|
||||||
|
int getConnectionTimeout() const;
|
||||||
|
void setConnectionTimeout(int msec);
|
||||||
|
|
||||||
|
int getResponseTimeout() const;
|
||||||
|
void setResponseTimeout(int msec);
|
||||||
|
|
||||||
|
QTcpSocket *getSocket();
|
||||||
|
|
||||||
|
bool connectToHost();
|
||||||
|
bool login();
|
||||||
|
bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin);
|
||||||
|
|
||||||
|
bool sendMail(MimeMessage &email);
|
||||||
|
void quit();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QTcpSocket *socket;
|
||||||
|
QString host;
|
||||||
|
int port;
|
||||||
|
ConnectionType connectionType;
|
||||||
|
QString name;
|
||||||
|
|
||||||
|
QString user;
|
||||||
|
QString password;
|
||||||
|
AuthMethod authMethod;
|
||||||
|
|
||||||
|
int connectionTimeout;
|
||||||
|
int responseTimeout;
|
||||||
|
|
||||||
|
QString responseText;
|
||||||
|
int responseCode;
|
||||||
|
|
||||||
|
class ResponseTimeoutException {};
|
||||||
|
void waitForResponse() throw (ResponseTimeoutException);
|
||||||
|
void sendMessage(const QString &text);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void smtpError(SmtpError e);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SMTPCLIENT_H
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef SMTPMIME_H
|
||||||
|
#define SMTPMIME_H
|
||||||
|
|
||||||
|
#include "smtpclient.h"
|
||||||
|
#include "mimepart.h"
|
||||||
|
#include "mimehtml.h"
|
||||||
|
#include "mimeattachment.h"
|
||||||
|
#include "mimemessage.h"
|
||||||
|
#include "mimetext.h"
|
||||||
|
#include "mimeinlinefile.h"
|
||||||
|
#include "mimefile.h"
|
||||||
|
|
||||||
|
#endif // SMTPMIME_H
|
Loading…
Reference in New Issue