Commit 1f39b73a authored by Sebastian Sauer's avatar Sebastian Sauer
Browse files

work-branch akonadi-port

svn path=/branches/work/akonadi-ports/kdepim/akonadi/; revision=982690
parent 6e8adbcf
set( maildispatcheragent_SRCS
maildispatcheragent.cpp
outboxqueue.cpp
sendjob.cpp
storeresultjob.cpp
#configdialog.cpp
)
# TODO get our own debug area
add_definitions( -DKDE_DEFAULT_DEBUG_AREA=5266 )
kde4_add_ui_files(maildispatcheragent_SRCS settings.ui)
kde4_add_kcfg_files(maildispatcheragent_SRCS settings.kcfgc)
kcfg_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/maildispatcheragent.kcfg org.kde.Akonadi.MailDispatcher.Settings)
qt4_add_dbus_adaptor(maildispatcheragent_SRCS
${CMAKE_CURRENT_BINARY_DIR}/org.kde.Akonadi.MailDispatcher.Settings.xml settings.h Settings
)
kde4_add_executable(akonadi_maildispatcher_agent RUN_UNINSTALLED ${maildispatcheragent_SRCS})
target_link_libraries(akonadi_maildispatcher_agent ${KDE4_AKONADI_LIBS} ${KDE4_AKONADI_KMIME_LIBS} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KMIME_LIBS} ${KDE4_MAILTRANSPORT_LIBS} outboxinterface )
install(TARGETS akonadi_maildispatcher_agent ${INSTALL_TARGETS_DEFAULT_ARGS})
install( FILES maildispatcheragent.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/akonadi/agents" )
#! /bin/sh
$XGETTEXT *.cpp -o $podir/akonadi_maildispatcher_agent.pot
* Once MoveJobs work, enable and test moving to sent-mail. Here is why it
doesn't work currently: Akonadi::Monitor sends itemMoved(...), but it is
not handled in AgentBase::Observer, and so it never gets "processed", and
is stuck in the Monitor/ChangeRecorder forever. (I.e. the resource will
not get any new notifications.) This has to be fixed in Akonadi, but that
means adding ObserverV2 or something.
* Figure out which / whether error strings should be i18n'd
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
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 "configdialog.h"
#include "settings.h"
#include <KConfigDialogManager>
//#include <akonadi/collectionmodel.h>
//#include <akonadi/collectionview.h>
//#include <akonadi/collectionfilterproxymodel.h>
#include <Akonadi/Collection>
#include <Akonadi/CollectionFetchJob>
#include <Akonadi/CollectionRequester>
using namespace Akonadi;
ConfigDialog::ConfigDialog(QWidget * parent) :
KDialog( parent )
{
ui.setupUi( mainWidget() );
mManager = new KConfigDialogManager( this, Settings::self() );
mManager->updateWidgets();
ui.outboxSelector->setMimeTypeFilter( QStringList() << QLatin1String( "message/rfc822" ) );
// collection has no name if I skip the fetch job and just do Collection c(id)
CollectionFetchJob *job = new CollectionFetchJob( Collection( Settings::self()->outbox() ), CollectionFetchJob::Base );
if( job->exec() )
{
Collection::List cs = job->collections();
if( !cs.empty() )
ui.outboxSelector->setCollection( cs.first() );
}
ui.sentMailSelector->setMimeTypeFilter( QStringList() << QLatin1String( "message/rfc822" ) );
job = new CollectionFetchJob( Collection( Settings::self()->sentMail() ), CollectionFetchJob::Base );
if( job->exec() )
{
Collection::List cs = job->collections();
if( !cs.empty() )
ui.sentMailSelector->setCollection( cs.first() );
}
// mCollectionView = new Akonadi::CollectionView( w );
// mCollectionView->setSelectionMode( QAbstractItemView::SingleSelection );
// connect( mCollectionView, SIGNAL(clicked(QModelIndex)),
// this, SLOT(collectionActivated(QModelIndex)) );
// l->addWidget( mCollectionView );
//
// mCollectionModel = new Akonadi::CollectionModel( this );
// Akonadi::CollectionFilterProxyModel *sortModel = new Akonadi::CollectionFilterProxyModel( this );
// sortModel->setDynamicSortFilter( true );
// sortModel->setSortCaseSensitivity( Qt::CaseInsensitive );
// sortModel->addMimeTypeFilter( "message/rfc822" );
// sortModel->setSourceModel( mCollectionModel );
// mCollectionView->setModel( sortModel );
connect( this, SIGNAL(okClicked()),
this, SLOT(save()) );
}
void ConfigDialog::save()
{
mManager->updateSettings();
// QModelIndex index = mCollectionView->currentIndex();
// if ( index.isValid() )
// {
// const Akonadi::Collection col = index.model()->data( index, Akonadi::CollectionModel::CollectionRole ).value<Akonadi::Collection>();
// if ( col.isValid() )
// {
// kDebug() << "Collection" << col.id() << "selected";
// Settings::self()->setOutbox( col.id() );
// }
// }
const Collection outbox = ui.outboxSelector->collection();
if ( outbox.isValid() )
{
kDebug() << "Collection" << outbox.id() << "selected for outbox.";
Settings::self()->setOutbox( outbox.id() );
}
const Collection sentMail = ui.sentMailSelector->collection();
if ( sentMail.isValid() )
{
kDebug() << "Collection" << sentMail.id() << "selected for sentMail.";
Settings::self()->setSentMail( sentMail.id() );
}
Settings::self()->writeConfig();
}
#include "configdialog.moc"
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
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 CONFIGDIALOG_H
#define CONFIGDIALOG_H
#include <KDialog>
#include "ui_settings.h"
class KConfigDialogManager;
class ConfigDialog : public KDialog
{
Q_OBJECT
public:
ConfigDialog( QWidget *parent = 0 );
private slots:
void save();
private:
Ui::ConfigDialog ui;
KConfigDialogManager *mManager;
};
#endif
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
Copyright 2009 Constantin Berzan <exit3219@gmail.com>
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 "maildispatcheragent.h"
//#include "configdialog.h"
#include "outboxqueue.h"
#include "sendjob.h"
#include "settings.h"
#include "settingsadaptor.h"
#include <QtDBus/QDBusConnection>
#include <QTimer>
#include <KDebug>
#include <KWindowSystem>
#include <Akonadi/ItemFetchScope>
using namespace Akonadi;
class MailDispatcherAgent::Private
{
public:
Private( MailDispatcherAgent *parent )
: q( parent )
{
currentJob = 0;
}
~Private()
{
}
MailDispatcherAgent * const q;
OutboxQueue *queue;
KJob *currentJob;
// slots:
void dispatch();
void itemFetched( Item &item );
void sendResult( KJob *job );
};
void MailDispatcherAgent::Private::dispatch()
{
Q_ASSERT( queue );
if( !q->isOnline() ) {
kDebug() << "Offline. See you later.";
return;
}
if( currentJob ) {
kDebug() << "Another job is active. See you later.";
return;
}
kDebug() << "Attempting to dispatch the next message.";
queue->fetchOne(); // will trigger itemFetched
}
MailDispatcherAgent::MailDispatcherAgent( const QString &id )
: AgentBase( id ),
d( new Private( this ) )
{
kDebug() << "maildispatcheragent: At your service, sir!";
new SettingsAdaptor( Settings::self() );
QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
Settings::self(), QDBusConnection::ExportAdaptors );
d->queue = new OutboxQueue( this );
connect( d->queue, SIGNAL( newItems() ), this, SLOT( dispatch() ) );
connect( d->queue, SIGNAL( itemReady( Akonadi::Item& ) ),
this, SLOT( itemFetched( Akonadi::Item& ) ) );
}
MailDispatcherAgent::~MailDispatcherAgent()
{
delete d;
}
void MailDispatcherAgent::configure( WId windowId )
{
Q_UNUSED( windowId );
kDebug() << "I have no options; you can't break me.";
}
void MailDispatcherAgent::doSetOnline( bool online )
{
Q_ASSERT( d->queue );
if( online ) {
kDebug() << "Online. Dispatching messages.";
QTimer::singleShot( 0, this, SLOT( dispatch() ) );
} else {
kDebug() << "Offline.";
// TODO: This way, the OutboxQueue will continue to react to changes in
// the outbox, but the MDA will just not send anything. Is this what we
// want?
}
AgentBase::doSetOnline( online );
}
void MailDispatcherAgent::Private::itemFetched( Item &item )
{
kDebug() << "Fetched item" << item.id() << "; creating SendJob.";
Q_ASSERT( currentJob == 0 );
currentJob = new SendJob( item );
connect( currentJob, SIGNAL( result( KJob* ) ),
q, SLOT( sendResult( KJob* ) ) );
currentJob->start();
}
void MailDispatcherAgent::Private::sendResult( KJob *job )
{
Q_ASSERT( job == currentJob );
currentJob->disconnect( q );
currentJob = 0;
if( job->error() ) {
// The SendJob gave the item an ErrorAttribute, so we don't have to
// do anything.
kDebug() << "Sending failed. error:" << job->errorString();
} else {
kDebug() << "Sending succeeded.";
}
// dispatch next message
QTimer::singleShot( 0, q, SLOT( dispatch() ) );
}
AKONADI_AGENT_MAIN( MailDispatcherAgent )
#include "maildispatcheragent.moc"
[Desktop Entry]
Name=Akonadi Mail Dispatcher Agent
Name[et]=Akonadi kirjade edastamise agent
Name[ga]=Gníomhaire Seolta Ríomhphoist Akonadi
Name[gl]=Cliente de despacho de correo de Akonadi
Name[ja]=Akonadi メール発送エージェント
Name[km]=ភ្នាក់ងារ​បញ្ជូន​សំបុត្រ Akonadi
Name[nds]=Akonadi-Nettpostverdeel-Hölper
Name[pt]=Agente de Envio de Correio do Akonadi
Name[pt_BR]=Agente de Envio de Correio do Akonadi
Name[sv]=Akonadi e-postavsändningsmodul
Name[tr]=Akonadi Posta Gönderim Aracısı
Name[uk]=Агент розподілу пошти Akonadi
Name[x-test]=xxAkonadi Mail Dispatcher Agentxx
Type=AkonadiAgent
Exec=akonadi_maildispatcher_agent
X-Akonadi-MimeTypes=message/rfc822
X-Akonadi-Capabilities=Unique,Autostart
X-Akonadi-Identifier=akonadi_maildispatcher_agent
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
Copyright 2009 Constantin Berzan <exit3219@gmail.com>
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 MAILDISPATCHERAGENT_H
#define MAILDISPATCHERAGENT_H
#include <Akonadi/AgentBase>
#include <Akonadi/Collection>
#include <Akonadi/Item>
/**
* This agent dispatches mail put into the outbox collection.
*/
class MailDispatcherAgent : public Akonadi::AgentBase
{
Q_OBJECT
public:
MailDispatcherAgent( const QString &id );
~MailDispatcherAgent();
public Q_SLOTS:
virtual void configure( WId windowId );
protected:
virtual void doSetOnline( bool online );
private:
class Private;
Private* const d;
Q_PRIVATE_SLOT( d, void dispatch() )
Q_PRIVATE_SLOT( d, void itemFetched( Akonadi::Item& ) )
Q_PRIVATE_SLOT( d, void sendResult( KJob* ) )
};
#endif // MAILDISPATCHERAGENT_H
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="maildispatcheragentrc"/>
<group name="General">
<entry name="Outbox" type="LongLong">
<label>Outbox collection id</label>
<default>-1</default>
</entry>
<entry name="SentMail" type="LongLong">
<label>Sent Mail collection id</label>
<default>-1</default>
</entry>
</group>
</kcfg>
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
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 "outboxqueue.h"
#include <KDebug>
#include <Akonadi/Attribute>
#include <Akonadi/Item>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <Akonadi/Monitor>
#include <kmime/kmime_message.h>
#include <boost/shared_ptr.hpp>
#include <outboxinterface/localfolders.h>
#include <outboxinterface/addressattribute.h>
#include <outboxinterface/dispatchmodeattribute.h>
#include <outboxinterface/sentcollectionattribute.h>
#include <outboxinterface/transportattribute.h>
using namespace Akonadi;
using namespace OutboxInterface;
/**
* @internal
*/
class OutboxQueue::Private
{
public:
Private( OutboxQueue *qq )
: q( qq )
, outbox( -1 )
{
}
OutboxQueue *const q;
Collection outbox;
Monitor *monitor;
QList<Item> queue;
void initQueue();
void addIfComplete( const Item &item );
// slots:
void collectionFetched( KJob *job );
void itemFetched( KJob *job );
void outboxChanged();
void itemAdded( const Item &item );
void itemChanged( const Item &item );
void itemMoved( const Item &item, const Collection &source, const Collection &dest );
void itemRemoved( const Item &item );
};
void OutboxQueue::Private::initQueue()
{
queue.clear();
kDebug() << "Fetching items in collection" << outbox.id();
ItemFetchJob *job = new ItemFetchJob( outbox );
job->fetchScope().fetchAllAttributes();
job->fetchScope().fetchFullPayload( false );
connect( job, SIGNAL( result( KJob* ) ), q, SLOT( collectionFetched( KJob* ) ) );
}
void OutboxQueue::Private::addIfComplete( const Item &item )
{
if( item.remoteId().isEmpty() ) {
kDebug() << "Item" << item.id() << "has an empty remoteId.";
// HACK:
// This probably means that it hasn't yet been stored on disk by the
// maildir resource, so I'll let it go for now, and process it when
// it's ready.
return;
}
if( !item.hasAttribute<AddressAttribute>() ||
!item.hasAttribute<DispatchModeAttribute>() ||
!item.hasAttribute<SentCollectionAttribute>() ||
!item.hasAttribute<TransportAttribute>() ) {
kWarning() << "Item" << item.id() << "does not have all required attributes.";
return;
}
if( !item.hasFlag( "queued" ) ) {
kDebug() << "Item" << item.id() << "has no 'queued' flag.";
return;
}
const DispatchModeAttribute *mA = item.attribute<DispatchModeAttribute>();
Q_ASSERT( mA );
if( mA->dispatchMode() == DispatchModeAttribute::AfterDueDate &&
mA->dueDate() > QDateTime::currentDateTime() ) {
kDebug() << "Item" << item.id() << "is to be sent in the future.";
return;
// TODO: QTimer to check again on due date.
}
const TransportAttribute *tA = item.attribute<TransportAttribute>();
Q_ASSERT( tA );
if( tA->transport() == 0 ) {
kWarning() << "Item" << item.id() << "has invalid transport.";
return;
}
// This check requires fetchFullPayload. -> slow (?)
/*
if( !item.hasPayload<KMime::Message::Ptr>() ) {
kWarning() << "Item" << item.id() << "does not have KMime::Message::Ptr payload.";
return;
}
*/
kDebug() << "Item" << item.id() << "is accepted into the queue.";
queue.append( item );
emit q->newItems();
}
void OutboxQueue::Private::collectionFetched( KJob *job )
{
if( job->error() ) {
kWarning() << "Failed to fetch outbox collection. Queue will be empty until the outbox changes.";
return;