Logo Search packages:      
Sourcecode: mailody-kde4 version File versions  Download package

sendmessage.cpp

/* This file is part of the KDE project

   Copyright (C) 2006-2008 Omat Holding B.V. <info@omat.nl>
   Copyright (C) 2007 Frode M. Døving <frode@lnix.net>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program 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
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301,USA.
*/

// Own
#include "sendmessage.h"
#include "setup.h"
#include "database.h"
#include "global.h"
#include <config-mailody.h>

// Qt
#include <QApplication>
#include <QFile>
#include <QTextCodec>

// KDEPIM
#include <kmime/kmime_message.h>
#include <kpimutils/linklocator.h>
#include <mailtransport/transport.h>
#include <mailtransport/transportmanager.h>
#include <mailtransport/transportjob.h>
#include <kpimidentities/identity.h>
#include <akonadi/item.h>
#include <akonadi/itemcreatejob.h>

// KDE
#include <KAboutData>
#include <KCodecs>
#include <KMessageBox>
#include <KMimeType>
#include <KProtocolManager>

#include <kio/job.h>

using namespace Mailody;

#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<KMime::Message> MessagePtr;

SendMessage::SendMessage( QObject *parent )
        : QObject( parent )
{
}

SendMessage::~SendMessage()
{
}

KMime::Message* SendMessage::compileMessage( SendType send,
        int identity, const QString& plain, const QString& html )
{
    using KMime::Message;
    using KMime::Content;

    const KPIMIdentities::Identity& ident =
        Global::identityManager()->identityForUoid( identity );

    QString name = ident.fullName();
    QString email = ident.emailAddr();
    int sendhtmlPart = ident.property( s_usehtml ).toInt();

    while ( name.isEmpty() || email.isEmpty() ) {
        QApplication::restoreOverrideCursor();
        int i = KMessageBox::warningContinueCancel( 0,
                i18n( "Settings are not complete, "
                      "complete them and try again..." ),
                i18n( "Settings" ) );
        if ( i == KMessageBox::Continue ) {
            Setup setup( 0,"Setup" );
            if ( setup.exec() != QDialog::Accepted )
                return new KMime::Message();

            name = ident.fullName();
            email = ident.emailAddr();
            sendhtmlPart = ident.property( s_usehtml ).toInt();
        } else
            return new KMime::Message();
    }

    Message *newMessage = new Message();
    newMessage->contentType()->setMimeType( "multipart/mixed" );
    newMessage->contentType()->setBoundary( KMime::multiPartBoundary() );

    KMime::Headers::From *fromAddress = new KMime::Headers::From();
    fromAddress->addAddress( email.trimmed().toLatin1(), name.toLatin1() );
    newMessage->setHeader( fromAddress );

    QStringList allTos;
    Database *conn = Database::dbinstance();

    KMime::Headers::To *toAddress = new KMime::Headers::To( newMessage );

    int total = m_tos.count();
    for ( int i = 0 ; i < total ; ++i ) {
        KMime::Types::Mailbox Address;
        Address.fromUnicodeString( m_tos.at( i ).trimmed() );

        toAddress->addAddress( Address );

        conn->addToRecentList( Address.address(), Address.name() );
        allTos.append( Address.address() );
    }

    KMime::Headers::Cc *ccAddress = new KMime::Headers::Cc( newMessage );
    total = m_ccs.count();
    for ( int i = 0 ; i < total ; ++i ) {
        KMime::Types::Mailbox Address;
        Address.fromUnicodeString( m_ccs.at( i ).trimmed() );

        ccAddress->addAddress( Address );

        conn->addToRecentList( Address.address(), Address.name() );
    }

    KMime::Headers::Bcc *bccAddress = new KMime::Headers::Bcc( newMessage );
    total = m_bccs.count();
    for ( int i = 0 ; i < total ; ++i ) {
        KMime::Types::Mailbox Address;
        Address.fromUnicodeString( m_bccs.at( i ).trimmed() );

        bccAddress->addAddress( Address );

        conn->addToRecentList( Address.address(), Address.name() );
    }

    if ( !ccAddress->isEmpty() )
        newMessage->setHeader( ccAddress );
    if ( !bccAddress->isEmpty() )
        newMessage->setHeader( bccAddress );
    if ( !toAddress->isEmpty() )
        newMessage->setHeader( toAddress );

    if ( !m_subject.isEmpty() ) {
        KMime::Headers::Subject *Subject = new KMime::Headers::Subject;
        Subject->fromUnicodeString( m_subject, encoding( m_subject ) );
        newMessage->setHeader( Subject );
    }

    KMime::Headers::Date *Date = new KMime::Headers::Date;
    Date->setDateTime( KDateTime::currentLocalDateTime() );
    newMessage->setHeader( Date );

    // useragent, similar to KMail - Copyright jstaniek.
    // user agent, e.g. Mailody/1.9.50 (Windows/5.0; KDE/3.97.1; i686; svn-762186; 2008-01-15)
    QStringList extraInfo;
#if defined MAILODY_SVN_REVISION_STRING && defined MAILODY_SVN_LAST_CHANGE
    extraInfo << MAILODY_SVN_REVISION_STRING << MAILODY_SVN_LAST_CHANGE;
#endif
    QString agent = KProtocolManager::userAgentForApplication( "Mailody",
                    KGlobal::mainComponent().aboutData()->version(), extraInfo );

    KMime::Headers::UserAgent *userAgent= new KMime::Headers::UserAgent;
    userAgent->fromUnicodeString( agent , "us-ascii" );
    newMessage->setHeader( userAgent );

    if ( !m_irt.isEmpty() ) {
        KMime::Headers::Generic *rt= new KMime::Headers::Generic;
        rt->fromUnicodeString( m_irt,encoding( m_irt ) );
        rt->setType( "In-Reply-To" );
        newMessage->setHeader( rt );
    }

    /*
    // set X-Mailody-Signature and X-Mailody-SP
    if ( send == Draft ) {
        // XMS
        KMime::Headers::Generic *xms = new KMime::Headers::Generic;
        QString sig = QString::fromUtf8( KCodecs::base64Encode( m_oldSig.toUtf8(), true ) );

        kDebug() << "CM-sig: " << sig;
        kDebug() << "CM-m_oldSig: " << m_oldSig;

        xms->fromUnicodeString( sig,encoding( sig ) );
        xms->setType( "X-Mailody-Signature" );
        newMessage->setHeader( xms );

        // XMSP
        KMime::Headers::Generic *xmsp = new KMime::Headers::Generic;
        QString p = QString::number( m_newpos );

        kDebug() << "CM-m_newpos: " << m_newpos;
        kDebug() << "CM-p: " << p;

        xmsp->fromUnicodeString( p,encoding( p ) );
        xmsp->setType( "X-Mailody-SP" );
        newMessage->setHeader( xmsp );
    }
    */

    // add a newMessageid.
    KMime::Headers::MessageID *mi = new KMime::Headers::MessageID;
    mi->generate( email.mid( email.indexOf( "@" )+1 ).toLatin1() );
    newMessage->setHeader( mi );

    Content *c_plain = new Content();
    if ( sendhtmlPart == 2 || m_attachments.count() > 0 || !html.isEmpty() ) {
        c_plain->contentType()->from7BitString( "text/plain" );
        c_plain->fromUnicodeString( plain );
        c_plain->assemble();
    } else {
        // no need for a multipart msg.
        newMessage->contentType()->from7BitString( "text/plain" );
        newMessage->fromUnicodeString( plain );
    }

    if (( sendhtmlPart == 1 || send == Draft ) && html.isEmpty() )
        newMessage->addContent( c_plain );
    else {
        // Make the html-part of the same message.
        Content *c_html = new Content();
        c_html->contentType()->from7BitString( "text/html" );

        if ( html.isEmpty() ) {
            using KPIMUtils::LinkLocator;
            const int flags = LinkLocator::PreserveSpaces |
                              LinkLocator::HighlightText;
            c_html->fromUnicodeString( Global::highlightText(
                                           LinkLocator::convertToHtml( plain, flags ) ) );
        } else {
            c_html->fromUnicodeString( html );
        }

        c_html->assemble();

        // Make a Content* that will hold the plain and html part.
        Content *c_maincontent = new Content();
        c_maincontent->contentType()->setMimeType( "multipart/alternative" );
        c_maincontent->contentType()->setBoundary( KMime::multiPartBoundary() );
        c_maincontent->addContent( c_plain );
        c_maincontent->addContent( c_html );
        c_maincontent->assemble();

        newMessage->addContent( c_maincontent );
    }

    // Hook in the attachments
    int totalSize = 0;
    QHash<KUrl, QString>::Iterator ita;
    for ( ita = m_attachments.begin(); ita != m_attachments.end(); ++ita ) {
        //TODO: network transparency....
        QFile file( ita.key().path() );
        if ( file.open( QIODevice::ReadOnly ) ) {
            QByteArray data = file.readAll();
            file.close();

            // convert to base64
            QByteArray final = KCodecs::base64Encode( data, true );

            // Add this part
            Content* c = new Content();
            c->setBody( final+"\n\n" );

            // Add a content type / find mime-type
            KMimeType::Ptr type = KMimeType::findByUrl( ita.key() );
            KMime::Headers::ContentType *ctt= new KMime::Headers::ContentType( c );
            ctt->fromUnicodeString( type->name(),encoding( type->name() ) );
            ctt->setName( ita.value(), "" );
            c->setHeader( ctt );

            // Set the encoding.
            KMime::Headers::ContentTransferEncoding *cte=
                new KMime::Headers::ContentTransferEncoding( c );
            cte->setEncoding( KMime::Headers::CEbase64 );
            cte->setDecoded( false );
            c->setHeader( cte );
            c->assemble();

            // Save the size.
            totalSize += file.size();

            newMessage->addContent( c );
        }
    }

    if ( totalSize > 2000000 ) {
        int i = KMessageBox::warningContinueCancel( 0,
                i18n( "The size of the attachments is %1, are you "
                      "sure you want to continue?",
                      KIO::convertSize( KIO::filesize_t( totalSize ) ) ),
                i18n( "Big Attachment" ),
                KStandardGuiItem::cont(),
                KStandardGuiItem::cancel(),
                "big_attachments_are_ok" );
        if ( i != KMessageBox::Continue )
            return new KMime::Message();
        else
            QApplication::restoreOverrideCursor();
    }

    newMessage->assemble();

    kDebug() << "newMessage compiled";
    return newMessage;
}

const char * SendMessage::encoding( const QString& data )
{
    static QTextCodec *local = KGlobal::locale()->codecForEncoding();
    kDebug() << "user has: " << local->name();

    if ( local->canEncode( data ) )
        return local->name();
    else
        return "utf-8";
}

void SendMessage::send( const Akonadi::Collection& folder, int identity,
                        const int transportId, const QString& plain, const QString& html )
{
//X     QApplication::setOverrideCursor( Qt::WaitCursor );
    KMime::Message *kmimeMessage = compileMessage( Final, identity, plain, html ); // send = true.
    const QByteArray cmsg = kmimeMessage->encodedContent( true ) + "\r\n";

    kDebug() << cmsg;

    if ( cmsg.isEmpty() )
        return;

    Akonadi::Item item( "message/rfc822" );
    item.setPayload( MessagePtr( kmimeMessage ) );

    new Akonadi::ItemCreateJob( item, folder, 0 );
    //connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotDone( KJob* ) ) );

    const KPIMIdentities::Identity& ident =
        Global::identityManager()->identityForUoid( identity );
    QString from = ident.emailAddr();

    MailTransport::Transport *base =
        MailTransport::TransportManager::self()->transportById( transportId );
    kDebug() << "Sending to:" << base->host() << base->port();

    MailTransport::TransportJob *job =
        MailTransport::TransportManager::self()->createTransportJob( transportId );

    if ( !job ) {
        kDebug() << "Not possible to create SMTP Job!";
        emit sendError( i18n( "Not possible to create SMTP Job!" ) );
        return;
    }

    job->setData( cmsg );
    job->setSender( from );
    job->setTo( m_tos );

    connect( job, SIGNAL( result( KJob* ) ), SLOT( slotResult( KJob* ) ) );
    MailTransport::TransportManager::self()->schedule( job );
}

void SendMessage::slotResult( KJob *job )
{
    kDebug();
    if ( job->error() )
        emit sendError( job->errorString() );
    else
        emit finished();
}

#include "sendmessage.moc"

Generated by  Doxygen 1.6.0   Back to index