diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv b/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv new file mode 100644 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-active-discard.siv @@ -0,0 +1,9 @@ +require ["date","relational","vacation"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if allof (not header :contains "X-Spam-Flag" "YES") +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + discard; +} \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv new file mode 100644 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-copy.siv @@ -0,0 +1,10 @@ +require ["vacation", "copy"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if false +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + redirect :copy "copy@example.org"; +} +discard; \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv new file mode 100644 --- /dev/null +++ b/libksieve/ksieveui/vacation/tests/data/vacation-deactive-send.siv @@ -0,0 +1,11 @@ +require ["vacation", "copy"]; +# EDITOR Roundcube (Managesieve) +# EDITOR_VERSION 8.2 +# rule:[Urlaub] +if false +{ + vacation :days 7 :addresses "test@test.de" :subject "XXX" "dsfgsdfgsdfg"; + redirect "redirect@example.org"; +} + +redirect :copy "argh@example.org"; \ No newline at end of file diff --git a/libksieve/ksieveui/vacation/tests/vacationutilstest.h b/libksieve/ksieveui/vacation/tests/vacationutilstest.h --- a/libksieve/ksieveui/vacation/tests/vacationutilstest.h +++ b/libksieve/ksieveui/vacation/tests/vacationutilstest.h @@ -33,6 +33,8 @@ void testParseScript(); void testParseScriptComplex(); void testParseScriptComplexTime(); + void testMailAction_data(); + void testMailAction(); void testWriteScript(); void testWriteSimpleScript(); void testUpdateVacationBlock(); diff --git a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp --- a/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp +++ b/libksieve/ksieveui/vacation/tests/vacationutilstest.cpp @@ -125,6 +125,38 @@ QCOMPARE(vacationD.endTime, QTime()); } +void VacationUtilsTest::testMailAction_data() +{ + QTest::addColumn("filename"); + QTest::addColumn("action"); + QTest::addColumn("recipient"); + + QTest::newRow("keep") << QString::fromLatin1("vacation-complex.siv") << (int)VacationUtils::Keep << QString(); + QTest::newRow("discard") << QString::fromLatin1("vacation-active-discard.siv") << (int)VacationUtils::Discard << QString(); + QTest::newRow("send") << QString::fromLatin1("vacation-deactive-send.siv") << (int)VacationUtils::Sendto << QString::fromLatin1("redirect@example.org"); + QTest::newRow("copy") << QString::fromLatin1("vacation-deactive-copy.siv") << (int)VacationUtils::CopyTo << QString::fromLatin1("copy@example.org"); +} + +void VacationUtilsTest::testMailAction() +{ + QFETCH(QString, filename); + QFETCH(int, action); + QFETCH(QString, recipient); + + QFile file(QLatin1String(VACATIONTESTDATADIR) + filename); + QVERIFY(file.open(QIODevice::ReadOnly)); + QString script = QString::fromUtf8(file.readAll()); + + VacationUtils::Vacation vacation = VacationUtils::parseScript(script); + QCOMPARE((int)vacation.mailAction, action); + QCOMPARE(vacation.mailActionRecipient, recipient); + + const QString composedScript = VacationUtils::composeScript(vacation); + vacation = VacationUtils::parseScript(composedScript); + QCOMPARE((int)vacation.mailAction, action); + QCOMPARE(vacation.mailActionRecipient, recipient); +} + void VacationUtilsTest::testParseScriptComplex() { QFile file(QLatin1String(VACATIONTESTDATADIR "vacation-complex.siv")); diff --git a/libksieve/ksieveui/vacation/vacation.cpp b/libksieve/ksieveui/vacation/vacation.cpp --- a/libksieve/ksieveui/vacation/vacation.cpp +++ b/libksieve/ksieveui/vacation/vacation.cpp @@ -123,6 +123,7 @@ mWasActive = active; if ( mDialog ) { mDialog->setActivateVacation( active && vacation.active ); + mDialog->setMailAction(vacation.mailAction, vacation.mailActionRecipient); mDialog->setSubject(vacation.subject); mDialog->setMessageText( vacation.messageText ); mDialog->setNotificationInterval( vacation.notificationInterval ); @@ -165,6 +166,8 @@ vacation.active = active; vacation.messageText = mDialog->messageText(); vacation.subject = mDialog->subject(); + vacation.mailAction = mDialog->mailAction(); + vacation.mailActionRecipient = mDialog->mailActionRecipient(); vacation.notificationInterval = mDialog->notificationInterval(); vacation.aliases = mDialog->mailAliases(); vacation.sendForSpam = mDialog->sendForSpam(); diff --git a/libksieve/ksieveui/vacation/vacationdialog.h b/libksieve/ksieveui/vacation/vacationdialog.h --- a/libksieve/ksieveui/vacation/vacationdialog.h +++ b/libksieve/ksieveui/vacation/vacationdialog.h @@ -15,6 +15,7 @@ #define KSIEVE_KSIEVEUI_VACATIONDIALOG_H #include +#include "vacationutils.h" template class QList; @@ -52,6 +53,10 @@ QString subject() const; void setSubject( const QString &subject ); + VacationUtils::MailAction mailAction() const; + QString mailActionRecipient() const; + void setMailAction (KSieveUi::VacationUtils::MailAction action, const QString &recipient); + int notificationInterval() const; void setNotificationInterval( int days ); diff --git a/libksieve/ksieveui/vacation/vacationdialog.cpp b/libksieve/ksieveui/vacation/vacationdialog.cpp --- a/libksieve/ksieveui/vacation/vacationdialog.cpp +++ b/libksieve/ksieveui/vacation/vacationdialog.cpp @@ -109,6 +109,21 @@ return mVacationEditWidget->setSubject(subject); } +VacationUtils::MailAction VacationDialog::mailAction() const +{ + return mVacationEditWidget->mailAction(); +} + +QString VacationDialog::mailActionRecipient() const +{ + return mVacationEditWidget->mailActionRecipient(); +} + +void VacationDialog::setMailAction(VacationUtils::MailAction action, const QString& recipient) +{ + mVacationEditWidget->setMailAction(action, recipient); +} + int VacationDialog::notificationInterval() const { return mVacationEditWidget->notificationInterval(); diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.h b/libksieve/ksieveui/vacation/vacationeditwidget.h --- a/libksieve/ksieveui/vacation/vacationeditwidget.h +++ b/libksieve/ksieveui/vacation/vacationeditwidget.h @@ -19,11 +19,13 @@ #define VACATIONEDITWIDGET_H #include +#include "vacationutils.h" class KIntSpinBox; class KLineEdit; class KDateComboBox; class KTimeComboBox; +class QComboBox; class QDate; class QTime; @@ -90,10 +92,15 @@ QTime endTime() const; void setEndTime( const QTime &endTime ); + VacationUtils::MailAction mailAction() const; + QString mailActionRecipient() const; + void setMailAction(VacationUtils::MailAction action, const QString &recipient); + void setDefault(); private Q_SLOTS: void slotIntervalSpinChanged( int value ); + void mailActionChanged(int index); protected: QCheckBox *mActiveCheck; @@ -104,6 +111,8 @@ QCheckBox *mDomainCheck; KLineEdit *mDomainEdit; KLineEdit *mSubject; + QComboBox *mMailAction; + KLineEdit *mMailActionRecipient; KDateComboBox *mStartDate; KTimeComboBox *mStartTime; QCheckBox *mStartTimeActive; diff --git a/libksieve/ksieveui/vacation/vacationeditwidget.cpp b/libksieve/ksieveui/vacation/vacationeditwidget.cpp --- a/libksieve/ksieveui/vacation/vacationeditwidget.cpp +++ b/libksieve/ksieveui/vacation/vacationeditwidget.cpp @@ -159,6 +159,30 @@ glay->addWidget( tmpLabel, row, 0 ); glay->addWidget( mMailAliasesEdit, row, 1 ); + // Action for incomming mails + mMailAction = new QComboBox(this); + for (int i=0; i<4; i++) { + mMailAction->addItem(VacationUtils::mailAction((VacationUtils::MailAction) i)); + } + mMailAction->setObjectName(QLatin1String("mMailAction")); + connect(mMailAction, SIGNAL(currentIndexChanged(int)), SLOT(mailActionChanged(int))); + + mMailActionRecipient = new KLineEdit(this); + mMailActionRecipient->setObjectName(QLatin1String("mMailActionRecipient")); + mMailActionRecipient->setClearButtonShown(true); + mMailActionRecipient->setEnabled(false); + + QHBoxLayout *hLayout = new QHBoxLayout(this); + + hLayout->addWidget(mMailAction); + hLayout->addWidget(mMailActionRecipient); + + ++row; + tmpLabel = new QLabel(i18n("&Action for incomming mails:"), this); + tmpLabel->setBuddy(mMailAction); + glay->addWidget(tmpLabel, row, 0); + glay->addLayout(hLayout, row, 1); + // "Send responses also to SPAM mail" checkbox: ++row; mSpamCheck = new QCheckBox( i18n("Do not send vacation replies to spam messages"), this ); @@ -362,6 +386,30 @@ } } +void VacationEditWidget::mailActionChanged(int action) +{ + bool enable = (action == VacationUtils::CopyTo || action == VacationUtils::Sendto); + mMailActionRecipient->setEnabled(enable); +} + + +void VacationEditWidget::setMailAction(VacationUtils::MailAction action, const QString &recipient) +{ + mMailAction->setCurrentIndex(action); + mMailActionRecipient->setText(recipient); +} + +VacationUtils::MailAction VacationEditWidget::mailAction() const +{ + return (VacationUtils::MailAction) mMailAction->currentIndex(); +} + +QString VacationEditWidget::mailActionRecipient() const +{ + return mMailActionRecipient->text(); +} + + void VacationEditWidget::enableDates( bool enable ) { mStartDate->setEnabled( enable ); @@ -384,5 +432,6 @@ setMailAliases( VacationUtils::defaultMailAliases() ); setSendForSpam( VacationUtils::defaultSendForSpam() ); setDomainName( VacationUtils::defaultDomainName() ); + setMailAction(VacationUtils::defaultMailAction(), QString()); setDomainCheck( false ); } diff --git a/libksieve/ksieveui/vacation/vacationpagewidget.cpp b/libksieve/ksieveui/vacation/vacationpagewidget.cpp --- a/libksieve/ksieveui/vacation/vacationpagewidget.cpp +++ b/libksieve/ksieveui/vacation/vacationpagewidget.cpp @@ -134,6 +134,7 @@ mVacationEditWidget->setActivateVacation( active && vacation.active ); mVacationEditWidget->setMessageText( vacation.messageText ); mVacationEditWidget->setSubject( vacation.subject ); + mVacationEditWidget->setMailAction(vacation.mailAction, vacation.mailActionRecipient); mVacationEditWidget->setNotificationInterval( vacation.notificationInterval ); mVacationEditWidget->setMailAliases( vacation.aliases ); mVacationEditWidget->setSendForSpam( vacation.sendForSpam ); @@ -165,6 +166,8 @@ vacation.active = active; vacation.messageText = mVacationEditWidget->messageText(); vacation.subject = mVacationEditWidget->subject(); + vacation.mailAction = mVacationEditWidget->mailAction(); + vacation.mailActionRecipient = mVacationEditWidget->mailActionRecipient(); vacation.notificationInterval = mVacationEditWidget->notificationInterval(); vacation.aliases = mVacationEditWidget->mailAliases(); vacation.sendForSpam = mVacationEditWidget->sendForSpam(); diff --git a/libksieve/ksieveui/vacation/vacationscriptextractor.h b/libksieve/ksieveui/vacation/vacationscriptextractor.h --- a/libksieve/ksieveui/vacation/vacationscriptextractor.h +++ b/libksieve/ksieveui/vacation/vacationscriptextractor.h @@ -20,6 +20,7 @@ #include "sieve-vacation.h" #include "util/util.h" +#include "vacationutils.h" #include #include @@ -432,7 +433,8 @@ // tagged args: Days, Addresses, Subject, VacationEnd, - IfBlock + IfBlock, + RedirectCommand }; public: VacationDataExtractor(); @@ -444,6 +446,8 @@ const QString & messageText() const { return mMessageText; } const QStringList & aliases() const { return mAliases; } const QString &ifComment() const { return mIfComment; } + VacationUtils::MailAction mailAction() const {return mMailAction;} + const QString &mailActionRecipient() const {return mMailActionRecipient;} const QString &subject() const { @@ -488,11 +492,16 @@ QStringList mAliases; bool mActive; bool mInIfBlock; + bool mFoundInBlock; int mBlockLevel; QString mIfComment; int mLineStart; int mLineEnd; + Context mMailActionContext; + VacationUtils::MailAction mMailAction; + QString mMailActionRecipient; + void reset(); }; diff --git a/libksieve/ksieveui/vacation/vacationscriptextractor.cpp b/libksieve/ksieveui/vacation/vacationscriptextractor.cpp --- a/libksieve/ksieveui/vacation/vacationscriptextractor.cpp +++ b/libksieve/ksieveui/vacation/vacationscriptextractor.cpp @@ -24,9 +24,12 @@ mNotificationInterval( 0 ) , mActive(true) , mInIfBlock(false) + , mFoundInBlock(false) , mBlockLevel(0) , mLineStart(0) , mLineEnd(0) + , mMailAction(VacationUtils::Keep) + , mMailActionContext(None) { } @@ -41,6 +44,16 @@ mLineStart = lineNumber; mInIfBlock = true; } + + if (commandFound() && (!mFoundInBlock || mBlockLevel > 0 )) { + if (identifier == QLatin1String("discard")) { + mMailAction = VacationUtils::Discard; + } else if (identifier == QLatin1String("redirect")) { + mMailAction = VacationUtils::Sendto; + mMailActionContext = RedirectCommand; + } + } + if ( identifier != QLatin1String("vacation") ) return; @@ -50,6 +63,7 @@ reset(); mContext = VacationCommand; + mFoundInBlock = (mBlockLevel > 0); } void VacationDataExtractor::commandEnd(int lineNumber) { @@ -57,6 +71,7 @@ mContext = VacationEnd; mLineEnd = lineNumber; } + mMailActionContext = None; } void VacationDataExtractor::error( const KSieve::Error & e ) @@ -106,6 +121,11 @@ void VacationDataExtractor::taggedArgument( const QString & tag ) { + if (mMailActionContext == RedirectCommand) { + if (tag == QLatin1String("copy")) { + mMailAction = VacationUtils::CopyTo; + } + } if ( mContext != VacationCommand ) return; if ( tag == QLatin1String("days") ) @@ -119,6 +139,9 @@ void VacationDataExtractor::stringArgument( const QString & string, bool, const QString & ) { + if (mMailActionContext == RedirectCommand) { + mMailActionRecipient = string; + } if ( mContext == Addresses ) { mAliases.push_back( string ); mContext = VacationCommand; @@ -163,6 +186,8 @@ void VacationDataExtractor::reset() { mContext = None; + mMailAction = VacationUtils::Keep; + mMailActionRecipient = QString(); mNotificationInterval = 0; mAliases.clear(); mMessageText.clear(); diff --git a/libksieve/ksieveui/vacation/vacationutils.h b/libksieve/ksieveui/vacation/vacationutils.h --- a/libksieve/ksieveui/vacation/vacationutils.h +++ b/libksieve/ksieveui/vacation/vacationutils.h @@ -24,8 +24,17 @@ namespace KSieveUi { namespace VacationUtils { + +enum MailAction { + Keep, + Discard, + Sendto, + CopyTo, +}; + QString defaultMessageText(); QString defaultSubject(); +MailAction defaultMailAction(); int defaultNotificationInterval(); KMime::Types::AddrSpecList defaultMailAliases(); bool defaultSendForSpam(); @@ -34,9 +43,11 @@ QDate defaultEndDate(); struct Vacation { - Vacation():valid(false), active(false), notificationInterval(1), sendForSpam(true) {} + Vacation():valid(false), active(false), notificationInterval(1), sendForSpam(true), mailAction(Keep) {} bool isValid() const {return valid;} + MailAction mailAction; + QString mailActionRecipient; bool valid; QString messageText; QString subject; @@ -59,6 +70,8 @@ QString updateVacationBlock(const QString &oldScript, const QString &newScript); +QString mailAction(MailAction action); + } } diff --git a/libksieve/ksieveui/vacation/vacationutils.cpp b/libksieve/ksieveui/vacation/vacationutils.cpp --- a/libksieve/ksieveui/vacation/vacationutils.cpp +++ b/libksieve/ksieveui/vacation/vacationutils.cpp @@ -41,6 +41,28 @@ return s.replace(QLatin1Char('\"'),QLatin1String("\\\"")); } +QString KSieveUi::VacationUtils::mailAction(KSieveUi::VacationUtils::MailAction action) +{ + switch (action) { + case Keep: + return i18n("Keep"); + case Discard: + return i18n("Discard"); + case Sendto: + return i18n("Redirect to"); + case CopyTo: + return i18n("Copy to"); + default: + kWarning() << "Unknown mail action" << action; + return i18n("Unkown action"); + } +} + +KSieveUi::VacationUtils::MailAction KSieveUi::VacationUtils::defaultMailAction() +{ + return KSieveUi::VacationUtils::Keep; +} + QString KSieveUi::VacationUtils::defaultSubject() { return i18n("Out of office till %1", QLocale().toString(QDate::currentDate().addDays(1))); @@ -111,6 +133,7 @@ if ( script.trimmed().isEmpty() ) { vacation.valid = false; vacation.active = false; + vacation.mailAction = VacationUtils::defaultMailAction(); vacation.messageText = VacationUtils::defaultMessageText(); vacation.subject = VacationUtils::defaultSubject(); vacation.notificationInterval = VacationUtils::defaultNotificationInterval(); @@ -141,6 +164,8 @@ } vacation.valid = true; vacation.active = vdx.active(); + vacation.mailAction = vdx.mailAction(); + vacation.mailActionRecipient = vdx.mailActionRecipient(); vacation.messageText = vdx.messageText().trimmed(); if (!vdx.subject().isEmpty()) { vacation.subject = vdx.subject().trimmed(); @@ -232,6 +257,14 @@ QString KSieveUi::VacationUtils::composeScript(const Vacation &vacation) { QStringList condition; + QStringList require; + + require << QLatin1String("vacation"); + + if (vacation.startDate.isValid() || vacation.endDate.isValid()) { + require << QLatin1String("date"); + require << QLatin1String("relational"); + } if (vacation.startDate.isValid()) { if (vacation.startTime.isValid()) { @@ -289,13 +322,25 @@ sVacation += dotstuff( vacation.messageText.isEmpty() ? VacationUtils::defaultMessageText() : vacation.messageText ); sVacation += QString::fromLatin1( "\n.\n;" ); + switch (vacation.mailAction) { + case VacationUtils::Keep: + break; + case VacationUtils::Discard: + sVacation += QLatin1String("\ndiscard;"); + break; + case VacationUtils::Sendto: + sVacation += QLatin1String("\nredirect \"") + vacation.mailActionRecipient + QLatin1String("\";"); + break; + case VacationUtils::CopyTo: + require << QLatin1String("copy"); + sVacation += QLatin1String("\nredirect :copy \"") + vacation.mailActionRecipient + QLatin1String("\";"); + break; + } + QString script; - if ( vacation.startDate.isValid() || vacation.endDate.isValid() ) { - script = QString::fromLatin1("require [\"vacation\", \"relational\", \"date\"];\n\n" ); - } else { - script = QString::fromLatin1("require \"vacation\";\n\n" ); - } + script = QLatin1String("require [\"%1\"];\n\n"); + script = script.arg(require.join(QLatin1String("\", \""))); if (condition.count() == 0) { if (vacation.active) {