diff --git a/CMakeLists.txt b/CMakeLists.txt index f7e8b1796..79ed89db0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ if (KDEPIM_BUILD_DESKTOP) set(kmailprivate_editor_potentialphishingemail_SRCS editor/potentialphishingemail/potentialphishingemailwarning.cpp editor/potentialphishingemail/potentialphishingemailjob.cpp + editor/potentialphishingemail/potentialphishingdetaildialog.cpp ) set(kmailprivate_dialogs_LIB_SRCS dialog/archivefolderdialog.cpp diff --git a/editor/kmcomposewin.cpp b/editor/kmcomposewin.cpp index 8b7d048db..fa48af5b8 100644 --- a/editor/kmcomposewin.cpp +++ b/editor/kmcomposewin.cpp @@ -184,6 +184,7 @@ #include #include #include +#include using Sonnet::DictionaryComboBox; using MailTransport::TransportManager; @@ -428,6 +429,7 @@ KMComposeWin::KMComposeWin(const KMime::Message::Ptr &aMsg, bool lastSignState, v->addWidget(mAttachmentMissing); mPotentialPhishingEmailWarning = new PotentialPhishingEmailWarning(this); + connect(mPotentialPhishingEmailWarning, SIGNAL(sendNow()), this, SLOT(slotCheckSendNowStep2())); v->addWidget(mPotentialPhishingEmailWarning); if (GlobalSettings::self()->showForgottenAttachmentWarning()) { @@ -2964,7 +2966,7 @@ void KMComposeWin::confirmBeforeSend() } } -void KMComposeWin::slotCheckSendNow() +void KMComposeWin::slotCheckSendNowStep2() { if (GlobalSettings::self()->confirmBeforeSend()) { confirmBeforeSend(); @@ -2985,6 +2987,37 @@ void KMComposeWin::slotCheckSendNow() } } +void KMComposeWin::slotCheckSendNow() +{ + PotentialPhishingEmailJob *job = new PotentialPhishingEmailJob(this); + KConfigGroup group( KSharedConfig::openConfig(), "PotentialPhishing"); + const QStringList whiteList = group.readEntry("whiteList", QStringList()); + qDebug()<<" whiteList"<setEmailWhiteList(whiteList); + QStringList lst; + lst << mComposerBase->to(); + if (!mComposerBase->cc().isEmpty()) + lst << mComposerBase->cc().split(QLatin1Char(',')); + if (!mComposerBase->bcc().isEmpty()) + lst << mComposerBase->bcc().split(QLatin1Char(',')); + job->setEmails(lst); + connect(job, SIGNAL(potentialPhishingEmailsFound(QStringList)), this, SLOT(slotPotentialPhishingEmailsFound(QStringList))); + job->start(); +} + +void KMComposeWin::slotPotentialPhishingEmailsFound(const QStringList &list) +{ +#if 1 + slotCheckSendNowStep2(); +#else + if (list.isEmpty()) { + slotCheckSendNowStep2(); + } else { + mPotentialPhishingEmailWarning->setPotentialPhisingEmail(list); + } +#endif +} + bool KMComposeWin::checkRecipientNumber() const { const int thresHold = GlobalSettings::self()->recipientThreshold(); diff --git a/editor/kmcomposewin.h b/editor/kmcomposewin.h index 018eb92a1..1bf82f19c 100644 --- a/editor/kmcomposewin.h +++ b/editor/kmcomposewin.h @@ -465,6 +465,8 @@ private Q_SLOTS: void slotSnippetWidgetVisibilityChanged(bool b); void slotOverwriteModeWasChanged(bool state); void slotExpandGroupResult(KJob *job); + void slotCheckSendNowStep2(); + void slotPotentialPhishingEmailsFound(const QStringList &list); public: // kmcommand // FIXME we need to remove these, but they're pure virtual in Composer. void addAttach(KMime::Content *msgPart); diff --git a/editor/potentialphishingemail/autotests/CMakeLists.txt b/editor/potentialphishingemail/autotests/CMakeLists.txt index cfddbddf1..31b137cf3 100644 --- a/editor/potentialphishingemail/autotests/CMakeLists.txt +++ b/editor/potentialphishingemail/autotests/CMakeLists.txt @@ -6,3 +6,9 @@ add_test(kmail_potentialphishingemailjobtest kmail_potentialphishingemailjobtest ecm_mark_as_test(kmail_potentialphishingemailjobtest) target_link_libraries( kmail_potentialphishingemailjobtest Qt5::Test KF5::Codecs) + +set( kmail_potentialphishingdetaildialogtest_SRCS potentialphishingdetaildialogtest.cpp ../potentialphishingdetaildialog.cpp ) +kde4_add_unit_test( kmail_potentialphishingdetaildialogtest ${kmail_potentialphishingdetaildialogtest_SRCS}) +target_link_libraries( kmail_potentialphishingdetaildialogtest ${QT_QTTEST_LIBRARY} ${KDE4_KDEUI_LIBS} ) + + diff --git a/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.cpp b/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.cpp new file mode 100644 index 000000000..1a09fdcb3 --- /dev/null +++ b/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.cpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2015 Montel Laurent + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + +#include "potentialphishingdetaildialogtest.h" +#include "../potentialphishingdetaildialog.h" +#include +#include +#include + +PotentialPhishingDetailDialogTest::PotentialPhishingDetailDialogTest(QObject *parent) + : QObject(parent) +{ + +} + +PotentialPhishingDetailDialogTest::~PotentialPhishingDetailDialogTest() +{ + +} + +void PotentialPhishingDetailDialogTest::shouldHaveDefaultValue() +{ + PotentialPhishingDetailDialog dlg; + QLabel *searchLabel = qFindChild(&dlg, QLatin1String("label")); + QVERIFY(searchLabel); + + QListWidget *listWidget = qFindChild(&dlg, QLatin1String("list_widget")); + QVERIFY(listWidget); + QCOMPARE(listWidget->count(), 0); +} + +void PotentialPhishingDetailDialogTest::shouldFillList() +{ + PotentialPhishingDetailDialog dlg; + QListWidget *listWidget = qFindChild(&dlg, QLatin1String("list_widget")); + QStringList lst; + lst << QLatin1String("bla"); + lst << QLatin1String("bli"); + lst << QLatin1String("blo"); + dlg.fillList(lst); + QCOMPARE(listWidget->count(), lst.count()); +} + +void PotentialPhishingDetailDialogTest::shouldClearListBeforeToAddNew() +{ + PotentialPhishingDetailDialog dlg; + QListWidget *listWidget = qFindChild(&dlg, QLatin1String("list_widget")); + QStringList lst; + lst << QLatin1String("bla"); + lst << QLatin1String("bli"); + lst << QLatin1String("blo"); + dlg.fillList(lst); + QCOMPARE(listWidget->count(), lst.count()); + lst.clear(); + lst << QLatin1String("bla"); + lst << QLatin1String("bli"); + dlg.fillList(lst); + QCOMPARE(listWidget->count(), lst.count()); +} + +void PotentialPhishingDetailDialogTest::shouldNotAddDuplicateEntries() +{ + PotentialPhishingDetailDialog dlg; + QListWidget *listWidget = qFindChild(&dlg, QLatin1String("list_widget")); + QStringList lst; + lst << QLatin1String("bla"); + lst << QLatin1String("blo"); + lst << QLatin1String("blo"); + dlg.fillList(lst); + QCOMPARE(listWidget->count(), (lst.count()-1)); + +} + +QTEST_KDEMAIN(PotentialPhishingDetailDialogTest, GUI) diff --git a/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.h b/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.h new file mode 100644 index 000000000..d66faef74 --- /dev/null +++ b/editor/potentialphishingemail/autotests/potentialphishingdetaildialogtest.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2015 Montel Laurent + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + +#ifndef POTENTIALPHISHINGDETAILDIALOGTEST_H +#define POTENTIALPHISHINGDETAILDIALOGTEST_H + +#include + +class PotentialPhishingDetailDialogTest : public QObject +{ + Q_OBJECT +public: + explicit PotentialPhishingDetailDialogTest(QObject *parent = 0); + ~PotentialPhishingDetailDialogTest(); +private Q_SLOTS: + void shouldHaveDefaultValue(); + void shouldFillList(); + void shouldClearListBeforeToAddNew(); + void shouldNotAddDuplicateEntries(); +}; + +#endif // POTENTIALPHISHINGDETAILDIALOGTEST_H diff --git a/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.cpp b/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.cpp index e281aff03..896ab8433 100644 --- a/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.cpp +++ b/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.cpp @@ -45,38 +45,36 @@ void PotentialPhishingEmailJobTest::shouldNotStartIfNoEmails() void PotentialPhishingEmailJobTest::shouldReturnPotentialPhishingEmails_data() { QTest::addColumn("listEmails"); + QTest::addColumn("whiteListEmail"); QTest::addColumn("hasPotentialPhishing"); - QTest::newRow("NoPotentialPhishing") << (QStringList() << QLatin1String("foo@kde.org")) << false; - QTest::newRow("HasPotentialPhishing") << (QStringList() << QLatin1String("\"bla@kde.org\" ")) << true; + QTest::newRow("NoPotentialPhishing") << (QStringList() << QLatin1String("foo@kde.org")) << QStringList() << false; + QTest::newRow("HasPotentialPhishing") << (QStringList() << QLatin1String("\"bla@kde.org\" ")) << QStringList() << true; + const QString email = QLatin1String("\"bla@kde.org\" "); + QTest::newRow("EmailInWhiteList") << (QStringList() << email) << (QStringList() << email) << false; + QTest::newRow("NotAllEmailInWhiteList") << (QStringList() << email << QLatin1String("\"c@kde.org\" ")) << (QStringList() << email) << true; } void PotentialPhishingEmailJobTest::shouldReturnPotentialPhishingEmails() { QFETCH( QStringList, listEmails ); + QFETCH( QStringList,whiteListEmail ); QFETCH( bool, hasPotentialPhishing ); + PotentialPhishingEmailJob *job = new PotentialPhishingEmailJob; + job->setEmailWhiteList(whiteListEmail); job->setEmails(listEmails); QVERIFY(job->start()); QCOMPARE(job->potentialPhisingEmails().isEmpty(), !hasPotentialPhishing); - } void PotentialPhishingEmailJobTest::shouldEmitSignal() { PotentialPhishingEmailJob *job = new PotentialPhishingEmailJob; - QSignalSpy spy(job, SIGNAL(potentialPhisingEmailsFound(QStringList))); + QSignalSpy spy(job, SIGNAL(potentialPhishingEmailsFound(QStringList))); job->setEmails((QStringList() << QLatin1String("\"bla@kde.org\" "))); job->start(); QCOMPARE(spy.count(), 1); } -void PotentialPhishingEmailJobTest::shouldNotEmitSignalWhenPotentialPhishingNotFound() -{ - PotentialPhishingEmailJob *job = new PotentialPhishingEmailJob; - QSignalSpy spy(job, SIGNAL(potentialPhisingEmailsFound(QStringList))); - job->setEmails((QStringList() << QLatin1String(""))); - job->start(); - QCOMPARE(spy.count(), 0); -} QTEST_MAIN(PotentialPhishingEmailJobTest) diff --git a/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.h b/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.h index c44bdac1b..3f971c54f 100644 --- a/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.h +++ b/editor/potentialphishingemail/autotests/potentialphishingemailjobtest.h @@ -35,7 +35,6 @@ private Q_SLOTS: void shouldReturnPotentialPhishingEmails_data(); void shouldReturnPotentialPhishingEmails(); void shouldEmitSignal(); - void shouldNotEmitSignalWhenPotentialPhishingNotFound(); }; #endif // POTENTIALPHISHINGEMAILJOBTEST_H diff --git a/editor/potentialphishingemail/potentialphishingdetaildialog.cpp b/editor/potentialphishingemail/potentialphishingdetaildialog.cpp new file mode 100644 index 000000000..7091015a7 --- /dev/null +++ b/editor/potentialphishingemail/potentialphishingdetaildialog.cpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2015 Montel Laurent + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + +#include "potentialphishingdetaildialog.h" +#include +#include +#include +#include +#include + + +PotentialPhishingDetailDialog::PotentialPhishingDetailDialog(QWidget *parent) + : KDialog(parent) +{ + setCaption( i18n( "Details" ) ); + setButtons( Ok|Cancel ); + setDefaultButton( Ok ); + + setModal( true ); + QWidget *mainWidget = new QWidget( this ); + QVBoxLayout *mainLayout = new QVBoxLayout( mainWidget ); + QLabel *lab = new QLabel(i18n("Select email to put in whitelist:")); + lab->setObjectName(QLatin1String("label")); + mainLayout->addWidget(lab); + + mListWidget = new QListWidget; + mListWidget->setObjectName(QLatin1String("list_widget")); + mainLayout->addWidget(mListWidget); + + connect(this, SIGNAL(okClicked()), this, SLOT(slotSave())); + setMainWidget(mainWidget); + readConfig(); +} + +PotentialPhishingDetailDialog::~PotentialPhishingDetailDialog() +{ + writeConfig(); +} + +void PotentialPhishingDetailDialog::fillList(const QStringList &lst) +{ + mListWidget->clear(); + QStringList emailsAdded; + Q_FOREACH(const QString & mail, lst) { + if (!emailsAdded.contains(mail)) { + QListWidgetItem *item = new QListWidgetItem(mListWidget); + item->setCheckState(Qt::Unchecked); + item->setText(mail); + emailsAdded << mail; + } + } +} + +void PotentialPhishingDetailDialog::readConfig() +{ + KConfigGroup group( KSharedConfig::openConfig(), "PotentialPhishingDetailDialog" ); + const QSize sizeDialog = group.readEntry( "Size", QSize(800,600) ); + if ( sizeDialog.isValid() ) { + resize( sizeDialog ); + } +} + +void PotentialPhishingDetailDialog::writeConfig() +{ + KConfigGroup group( KSharedConfig::openConfig(), "PotentialPhishingDetailDialog" ); + group.writeEntry( "Size", size() ); +} + +void PotentialPhishingDetailDialog::slotSave() +{ + KConfigGroup group( KSharedConfig::openConfig(), "PotentialPhishing"); + QStringList potentialPhishing = group.readEntry("whiteList", QStringList()); + for (int i=0; i < mListWidget->count(); ++i) { + QListWidgetItem *item = mListWidget->item(i); + if (item->checkState() == Qt::Checked) { + QString email = item->text(); + if (!potentialPhishing.contains(email)) { + potentialPhishing << email; + } + } + } + group.writeEntry( "whiteList", potentialPhishing); + accept(); +} diff --git a/editor/potentialphishingemail/potentialphishingdetaildialog.h b/editor/potentialphishingemail/potentialphishingdetaildialog.h new file mode 100644 index 000000000..a3a6969b9 --- /dev/null +++ b/editor/potentialphishingemail/potentialphishingdetaildialog.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015 Montel Laurent + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + +#ifndef POTENTIALPHISHINGDETAILDIALOG_H +#define POTENTIALPHISHINGDETAILDIALOG_H + +#include +class QListWidget; +class PotentialPhishingDetailDialog : public KDialog +{ + Q_OBJECT +public: + explicit PotentialPhishingDetailDialog(QWidget *parent=0); + ~PotentialPhishingDetailDialog(); + + void fillList(const QStringList &lst); + +private slots: + void slotSave(); + +private: + void readConfig(); + void writeConfig(); + QListWidget *mListWidget; +}; + +#endif // POTENTIALPHISHINGDETAILDIALOG_H diff --git a/editor/potentialphishingemail/potentialphishingemailjob.cpp b/editor/potentialphishingemail/potentialphishingemailjob.cpp index 0c7d2d7dc..c0fb4e333 100644 --- a/editor/potentialphishingemail/potentialphishingemailjob.cpp +++ b/editor/potentialphishingemail/potentialphishingemailjob.cpp @@ -32,6 +32,11 @@ PotentialPhishingEmailJob::~PotentialPhishingEmailJob() } +void PotentialPhishingEmailJob::setEmailWhiteList(const QStringList &emails) +{ + mEmailWhiteList = emails; +} + void PotentialPhishingEmailJob::setEmails(const QStringList &emails) { mEmails = emails; @@ -50,18 +55,18 @@ bool PotentialPhishingEmailJob::start() return false; } Q_FOREACH(const QString &addr, mEmails) { - QString tname, temail; - KEmailAddress::extractEmailAddressAndName( addr, temail, tname ); // ignore return value - // which is always false - if (tname.contains(QLatin1String("@"))) { //Potential address - if (temail != tname) { - mPotentialPhisingEmails.append(addr); + if (!mEmailWhiteList.contains(addr.trimmed())) { + QString tname, temail; + KEmailAddress::extractEmailAddressAndName( addr, temail, tname ); // ignore return value + // which is always false + if (tname.contains(QLatin1String("@"))) { //Potential address + if (temail != tname) { + mPotentialPhisingEmails.append(addr); + } } } } - if (!mPotentialPhisingEmails.isEmpty()) { - Q_EMIT potentialPhisingEmailsFound(mPotentialPhisingEmails); - } + Q_EMIT potentialPhishingEmailsFound(mPotentialPhisingEmails); deleteLater(); return true; } diff --git a/editor/potentialphishingemail/potentialphishingemailjob.h b/editor/potentialphishingemail/potentialphishingemailjob.h index 5bff0aeb0..0a0786ad8 100644 --- a/editor/potentialphishingemail/potentialphishingemailjob.h +++ b/editor/potentialphishingemail/potentialphishingemailjob.h @@ -31,16 +31,19 @@ public: explicit PotentialPhishingEmailJob(QObject *parent = 0); ~PotentialPhishingEmailJob(); + void setEmailWhiteList(const QStringList &emails); void setEmails(const QStringList &emails); + QStringList potentialPhisingEmails() const; bool start(); Q_SIGNALS: - void potentialPhisingEmailsFound(const QStringList &emails); + void potentialPhishingEmailsFound(const QStringList &emails); private: QStringList mEmails; QStringList mPotentialPhisingEmails; + QStringList mEmailWhiteList; }; #endif // POTENTIALPHISHINGEMAILJOB_H diff --git a/editor/potentialphishingemail/potentialphishingemailwarning.cpp b/editor/potentialphishingemail/potentialphishingemailwarning.cpp index 10f816d28..2cfcb93f4 100644 --- a/editor/potentialphishingemail/potentialphishingemailwarning.cpp +++ b/editor/potentialphishingemail/potentialphishingemailwarning.cpp @@ -20,6 +20,10 @@ #include "potentialphishingemailwarning.h" +#include "potentialphishingdetaildialog.h" +#include +#include +#include PotentialPhishingEmailWarning::PotentialPhishingEmailWarning(QWidget *parent) : KMessageWidget(parent) @@ -28,6 +32,13 @@ PotentialPhishingEmailWarning::PotentialPhishingEmailWarning(QWidget *parent) setCloseButtonVisible(true); setMessageType(Warning); setWordWrap(true); + + setText(i18n("Some address mail seems a potential phishing email (Details...)")); + + connect(this, SIGNAL(linkActivated(QString)), SLOT(slotShowDetails(QString))); + QAction *action = new QAction(i18n( "Send Now" ), this ); + connect( action, SIGNAL(triggered(bool)), SIGNAL(sendNow()) ); + addAction( action ); } PotentialPhishingEmailWarning::~PotentialPhishingEmailWarning() @@ -35,7 +46,20 @@ PotentialPhishingEmailWarning::~PotentialPhishingEmailWarning() } -void PotentialPhishingEmailWarning::setWarningText(const QString &text) +void PotentialPhishingEmailWarning::slotShowDetails(const QString &link) +{ + if (link == QLatin1String("phishingdetails")) { + QPointer dlg = new PotentialPhishingDetailDialog(this); + dlg->fillList(mPotentialPhishingEmails); + dlg->exec(); + delete dlg; + } +} + +void PotentialPhishingEmailWarning::setPotentialPhisingEmail(const QStringList &lst) { - animatedShow(); + mPotentialPhishingEmails = lst; + if (!mPotentialPhishingEmails.isEmpty()) { + animatedShow(); + } } diff --git a/editor/potentialphishingemail/potentialphishingemailwarning.h b/editor/potentialphishingemail/potentialphishingemailwarning.h index fedd7b3fd..e8397be8b 100644 --- a/editor/potentialphishingemail/potentialphishingemailwarning.h +++ b/editor/potentialphishingemail/potentialphishingemailwarning.h @@ -30,7 +30,15 @@ public: explicit PotentialPhishingEmailWarning(QWidget *parent = 0); ~PotentialPhishingEmailWarning(); - void setWarningText(const QString &text); + void setPotentialPhisingEmail(const QStringList &lst); + +Q_SIGNALS: + void sendNow(); + +private slots: + void slotShowDetails(const QString &link); +private: + QStringList mPotentialPhishingEmails; }; #endif // POTENTIALPHISHINGEMAILWARNING_H