예제 #1
0
QByteArray getRefStr(const KMime::Message::Ptr &msg)
{
    QByteArray firstRef, lastRef, refStr, retRefStr;
    int i, j;

    if (auto hdr = msg->references(false)) {
        refStr = hdr->as7BitString(false).trimmed();
    }

    if (refStr.isEmpty()) {
        return msg->messageID()->as7BitString(false);
    }

    i = refStr.indexOf('<');
    j = refStr.indexOf('>');
    firstRef = refStr.mid(i, j - i + 1);
    if (!firstRef.isEmpty()) {
        retRefStr = firstRef + ' ';
    }

    i = refStr.lastIndexOf('<');
    j = refStr.lastIndexOf('>');

    lastRef = refStr.mid(i, j - i + 1);
    if (!lastRef.isEmpty() && lastRef != firstRef) {
        retRefStr += lastRef + ' ';
    }

    retRefStr += msg->messageID()->as7BitString(false);
    return retRefStr;
}
예제 #2
0
void initHeader(const KMime::Message::Ptr &message)
{
    message->removeHeader<KMime::Headers::To>();
    message->removeHeader<KMime::Headers::Subject>();
    message->date()->setDateTime(QDateTime::currentDateTime());

    const QStringList extraInfo = QStringList() << QSysInfo::prettyProductName();
    message->userAgent()->fromUnicodeString(QString("%1/%2(%3)").arg(QString::fromLocal8Bit("Kube")).arg("0.1").arg(extraInfo.join(",")), "utf-8");
    // This will allow to change Content-Type:
    message->contentType()->setMimeType("text/plain");
}
예제 #3
0
void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward)
{
    //FIXME
    // MessageCore::ImageCollector ic;
    // ic.collectImagesFrom(mOrigMsg.data());

    // Now, delete the old content and set the new content, which
    // is either only the new text or the new text with some attachments.
    auto parts = msg->contents();
    foreach (KMime::Content *content, parts) {
        msg->removeContent(content, true/*delete*/);
    }
예제 #4
0
void ComposerTest::testBug271192()
{
    const QString displayName = QStringLiteral("Интернет-компания example");
    const QString mailbox = QStringLiteral("*****@*****.**");
    Composer *composer = new Composer;
    fillComposerData(composer);
    composer->infoPart()->setTo(QStringList() << (displayName + QLatin1String(" <") + mailbox + QLatin1String(">")));
    QVERIFY(composer->exec());
    QCOMPARE(composer->resultMessages().size(), 1);
    const KMime::Message::Ptr message = composer->resultMessages().first();
    QCOMPARE(message->to()->displayNames().size(), 1);
    QCOMPARE(message->to()->displayNames().first().toUtf8(), displayName.toUtf8());
    delete composer;
    composer = Q_NULLPTR;
}
예제 #5
0
void EwsMtaResource::sendItem(const Akonadi::Item &item)
{
    qDebug() << "sendItem" << item.remoteId();

    if (!connectEws()) {
        itemSent(item, TransportFailed, i18n("Unable to connect to master EWS resource"));
        return;
    }

    mItemHash.insert(item.remoteId(), item);

    KMime::Message::Ptr msg = item.payload<KMime::Message::Ptr>();
    QByteArray mimeContent = msg->encodedContent(true);
    mEwsResource->sendMessage(item.remoteId(), mimeContent);
}
예제 #6
0
파일: kmreaderwin.cpp 프로젝트: KDE/kdepim
bool KMReaderWin::printSelectedText(bool preview)
{
    const QString str = mViewer->selectedText();
    if (str.isEmpty()) {
        return false;
    }
    ::MessageComposer::Composer *composer = new ::MessageComposer::Composer;
    composer->textPart()->setCleanPlainText(str);
    composer->textPart()->setWrappedPlainText(str);
    KMime::Message::Ptr messagePtr = message().payload<KMime::Message::Ptr>();
    composer->infoPart()->setFrom(messagePtr->from()->asUnicodeString());
    composer->infoPart()->setTo(QStringList() << messagePtr->to()->asUnicodeString());
    composer->infoPart()->setCc(QStringList() << messagePtr->cc()->asUnicodeString());
    composer->infoPart()->setSubject(messagePtr->subject()->asUnicodeString());
    composer->setProperty("preview", preview);
    connect(composer, &::MessageComposer::Composer::result, this, &KMReaderWin::slotPrintComposeResult);
    composer->start();
    return true;
}
예제 #7
0
파일: mbox.cpp 프로젝트: pvuorela/kcalcore
// Appended entries works as follows: When an mbox file is loaded from disk,
// d->mInitialMboxFileSize is set to the file size at that moment. New entries
// are stored in memory (d->mAppendedEntries). The initial file size and the size
// of the buffer determine the offset for the next message to append.
MBoxEntry MBox::appendMessage( const KMime::Message::Ptr &entry )
{
  // It doesn't make sense to add entries when we don't have an reference file.
  Q_ASSERT( !d->mMboxFile.fileName().isEmpty() );

  const QByteArray rawEntry = MBoxPrivate::escapeFrom( entry->encodedContent() );

  if ( rawEntry.size() <= 0 ) {
    kDebug() << "Message added to folder `" << d->mMboxFile.fileName()
             << "' contains no data. Ignoring it.";
    return MBoxEntry();
  }

  int nextOffset = d->mAppendedEntries.size(); // Offset of the appended message

  // Make sure the byte array is large enough to check for an end character.
  // Then check if the required newlines are there.
  if ( nextOffset < 1 && d->mMboxFile.size() > 0 ) { // Empty, add one empty line
    d->mAppendedEntries.append( "\n" );
    ++nextOffset;
  } else if ( nextOffset == 1 && d->mAppendedEntries.at( 0 ) != '\n' ) {
    // This should actually not happen, but catch it anyway.
    if ( d->mMboxFile.size() < 0 ) {
      d->mAppendedEntries.append( "\n" );
      ++nextOffset;
    }
  } else if ( nextOffset >= 2 ) {
    if ( d->mAppendedEntries.at( nextOffset - 1 ) != '\n' ) {
      if ( d->mAppendedEntries.at( nextOffset ) != '\n' ) {
        d->mAppendedEntries.append( "\n\n" );
        nextOffset += 2;
      } else {
        d->mAppendedEntries.append( "\n" );
        ++nextOffset;
      }
    }
  }

  const QByteArray separator = MBoxPrivate::mboxMessageSeparator( rawEntry );
  d->mAppendedEntries.append( separator );
  d->mAppendedEntries.append( rawEntry );
  if ( rawEntry[rawEntry.size() - 1] != '\n' ) {
    d->mAppendedEntries.append( "\n\n" );
  } else {
    d->mAppendedEntries.append( "\n" );
  }

  MBoxEntry resultEntry;
  resultEntry.d->mOffset = d->mInitialMboxFileSize + nextOffset;
  resultEntry.d->mMessageSize = rawEntry.size();
  resultEntry.d->mSeparatorSize = separator.size();
  d->mEntries << resultEntry;

  return resultEntry;
}
예제 #8
0
void ComposerTest::testAttachments()
{
    Composer *composer = new Composer;
    fillComposerData(composer);
    AttachmentPart::Ptr attachment = AttachmentPart::Ptr(new AttachmentPart);
    attachment->setData("abc");
    attachment->setMimeType("x-some/x-type");
    composer->addAttachmentPart(attachment);

    QVERIFY(composer->exec());
    QCOMPARE(composer->resultMessages().size(), 1);
    KMime::Message::Ptr message = composer->resultMessages().first();
    delete composer;
    composer = Q_NULLPTR;

    // multipart/mixed
    {
        QVERIFY(message->contentType(false));
        QCOMPARE(message->contentType()->mimeType(), QByteArray("multipart/mixed"));
        QCOMPARE(message->contents().count(), 2);
        // text/plain
        {
            Content *plain = message->contents().at(0);
            QVERIFY(plain->contentType(false));
            QCOMPARE(plain->contentType()->mimeType(), QByteArray("text/plain"));
        }
        // x-some/x-type (attachment)
        {
            Content *plain = message->contents().at(1);
            QVERIFY(plain->contentType(false));
            QCOMPARE(plain->contentType()->mimeType(), QByteArray("x-some/x-type"));
        }
    }
}
예제 #9
0
bool KMail::Util::handleClickedURL( const KUrl &url, const QSharedPointer<MailCommon::FolderCollection> &folder )
{
  if ( url.protocol() == QLatin1String( "mailto" ) )
  {
    KMime::Message::Ptr msg ( new KMime::Message );
    uint identity = folder->identity();
    MessageHelper::initHeader( msg, KMKernel::self()->identityManager(), identity );
    msg->contentType()->setCharset("utf-8");

    QMap<QString, QString> fields =  MessageCore::StringUtil::parseMailtoUrl( url );

    msg->to()->fromUnicodeString( fields.value( "to" ),"utf-8" );
    if ( !fields.value( "subject" ).isEmpty() )
      msg->subject()->fromUnicodeString( fields.value( "subject" ),"utf-8" );
    if ( !fields.value( "body" ).isEmpty() )
      msg->setBody( fields.value( "body" ).toUtf8() );
    if ( !fields.value( "cc" ).isEmpty() )
      msg->cc()->fromUnicodeString( fields.value( "cc" ),"utf-8" );

    TemplateParser::TemplateParser parser( msg, TemplateParser::TemplateParser::NewMessage );
    parser.setIdentityManager( KMKernel::self()->identityManager() );
    parser.process( msg, folder->collection() );

    KMail::Composer * win = KMail::makeComposer( msg, false, false, KMail::Composer::New, identity );
    win->setFocusToSubject();
    win->setCollectionForNewMessage( folder->collection() );
    win->show();
    return true;
  } else {
    kWarning() << "Can't handle URL:" << url;
    return false;
  }
}
예제 #10
0
bool KMail::Util::handleClickedURL( const KUrl &url )
{
  if ( url.protocol() == QLatin1String( "mailto" ) )
  {
    KMime::Message::Ptr msg ( new KMime::Message );
    MessageHelper::initHeader( msg, KMKernel::self()->identityManager(), 0 );
    msg->contentType()->setCharset("utf-8");

    QMap<QString, QString> fields =  MessageCore::StringUtil::parseMailtoUrl( url );

    msg->to()->fromUnicodeString( fields.value( "to" ),"utf-8" );
    if ( !fields.value( "subject" ).isEmpty() )
      msg->subject()->fromUnicodeString( fields.value( "subject" ),"utf-8" );
    if ( !fields.value( "body" ).isEmpty() )
      msg->setBody( fields.value( "body" ).toUtf8() );
    if ( !fields.value( "cc" ).isEmpty() )
      msg->cc()->fromUnicodeString( fields.value( "cc" ),"utf-8" );

    KMail::Composer * win = KMail::makeComposer( msg, false, false,KMail::Composer::New, 0 );
    win->setFocusToSubject();
    win->show();
    return true;
  } else {
    kWarning() << "Can't handle URL:" << url;
    return false;
  }
}
예제 #11
0
Item Serializer::createItemFromNote(Domain::Note::Ptr note)
{
    NoteUtils::NoteMessageWrapper builder;
    builder.setTitle(note->title());
    builder.setText(note->text());

    KMime::Message::Ptr message = builder.message();

    if (!note->property("relatedUid").toString().isEmpty()) {
        auto relatedHeader = new KMime::Headers::Generic("X-Zanshin-RelatedProjectUid");
        relatedHeader->from7BitString(note->property("relatedUid").toString().toUtf8());
        message->appendHeader(relatedHeader);
    }

    Akonadi::Item item;
    if (note->property("itemId").isValid()) {
        item.setId(note->property("itemId").value<Akonadi::Item::Id>());
    }
    item.setMimeType(Akonadi::NoteUtils::noteMimeType());
    item.setPayload(message);
    return item;
}
예제 #12
0
bool AkonadiBrowserSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
    if (mBrowserModel->itemDisplayMode() == AkonadiBrowserModel::CalendarMode) {
        if (left.column() == 1 || left.column() == 2) {
            const Item leftItem = left.data(EntityTreeModel::ItemRole).value<Item>();
            const Item rightItem = right.data(EntityTreeModel::ItemRole).value<Item>();
            if (!leftItem.hasPayload<IncidencePtr>() || !rightItem.hasPayload<IncidencePtr>()) {
                return false;
            }
            const IncidencePtr leftInc = leftItem.payload<IncidencePtr>();
            const IncidencePtr rightInc = rightItem.payload<IncidencePtr>();

            if (left.column() == 1) {
                return leftInc->dtStart() < rightInc->dtStart();
            } else if (left.column() == 2) {
                return leftInc->dateTime(KCalCore::IncidenceBase::RoleEnd) < rightInc->dateTime(KCalCore::IncidenceBase::RoleEnd);
            }
        }
    } else if (mBrowserModel->itemDisplayMode() == AkonadiBrowserModel::MailMode) {
        if (left.column() == 2) {
            const Item leftItem = left.data(EntityTreeModel::ItemRole).value<Item>();
            const Item rightItem = right.data(EntityTreeModel::ItemRole).value<Item>();
            if (!leftItem.hasPayload<KMime::Message::Ptr>() || !rightItem.hasPayload<KMime::Message::Ptr>()) {
                return false;
            }
            const KMime::Message::Ptr leftMail = leftItem.payload<KMime::Message::Ptr>();
            const KMime::Message::Ptr rightMail = rightItem.payload<KMime::Message::Ptr>();
            const KMime::Headers::Date *ldate = leftMail->date(false);
            const KMime::Headers::Date *rdate = rightMail->date(false);
            if (ldate && rdate) {
                return ldate->dateTime() < rdate->dateTime();
            } else {
                return false;
            }
        }
    }

    return QSortFilterProxyModel::lessThan(left, right);
}
예제 #13
0
void ComposerTest::testNonAsciiHeaders()
{
    Composer *composer = new Composer;
    fillComposerData(composer);

    const QString mailbox = QStringLiteral(" <*****@*****.**>");
    const QString fromDisplayName = QStringLiteral("Hellö");
    const QString toDisplayName = QStringLiteral("æſłĸð");
    const QString ccDisplayName = QStringLiteral("Вася");
    const QString bccDisplayName = QStringLiteral("ĸłſðđøþĸµ»«„¢þµ¢”«ł„·ĸ”");
    const QString replyToDisplayName = QStringLiteral("æĸſłð˝đВасяðæĸđ");
    const QString from = fromDisplayName + mailbox;
    const QString to = toDisplayName + mailbox;
    const QString cc = ccDisplayName + mailbox;
    const QString bcc = bccDisplayName + mailbox;
    const QString replyto = replyToDisplayName + mailbox;

    composer->infoPart()->setFrom(from);
    composer->infoPart()->setTo(QStringList() << to);
    composer->infoPart()->setCc(QStringList() << cc);
    composer->infoPart()->setBcc(QStringList() << bcc);
    composer->infoPart()->setReplyTo(replyto);

    QVERIFY(composer->exec());
    QCOMPARE(composer->resultMessages().size(), 1);
    const KMime::Message::Ptr message = composer->resultMessages().first();
    message->assemble();
    message->parse();
    QCOMPARE(message->bcc(false)->displayNames().size(), 1);
    QCOMPARE(message->to(false)->displayNames().size(), 1);
    QCOMPARE(message->cc(false)->displayNames().size(), 1);
    QCOMPARE(message->from(false)->displayNames().size(), 1);
    QCOMPARE(message->replyTo(false)->displayNames().size(), 1);
    QCOMPARE(message->from()->displayNames().first(), fromDisplayName);
    QCOMPARE(message->to()->displayNames().first(), toDisplayName);
    QCOMPARE(message->cc()->displayNames().first(), ccDisplayName);
    QCOMPARE(message->bcc()->displayNames().first(), bccDisplayName);
    QCOMPARE(message->replyTo()->displayNames().first(), replyToDisplayName);
    delete composer;
    composer = Q_NULLPTR;
}
예제 #14
0
void KMail::Util::lastEncryptAndSignState(bool &lastEncrypt, bool &lastSign, const KMime::Message::Ptr& msg)
{
  lastSign = KMime::isSigned(msg.get());
  lastEncrypt = KMime::isEncrypted(msg.get());
}
예제 #15
0
void MailClient::send( const KPIMIdentities::Identity &identity,
                       const QString &from, const QString &_to,
                       const QString &cc, const QString &subject,
                       const QString &body, bool hidden, bool bccMe,
                       const QString &attachment, const QString &mailTransport )
{
  Q_UNUSED( identity );
  Q_UNUSED( hidden );

#ifdef MAILCLIENTTEST_UNITTEST
  mUnitTestResult.message = KMime::Message::Ptr();
  mUnitTestResult.from.clear();
  mUnitTestResult.to.clear();
  mUnitTestResult.cc.clear();
  mUnitTestResult.bcc.clear();
  mUnitTestResult.transportId = -1;
#endif

  if ( !MailTransport::TransportManager::self()->showTransportCreationDialog(
        0, MailTransport::TransportManager::IfNoTransportExists ) ) {
    kError() << "Error while creating transport";
    emit finished( ResultErrorCreatingTransport, i18n( "Error while creating transport" ) );
    return;
  }

  // We must have a recipients list for most MUAs. Thus, if the 'to' list
  // is empty simply use the 'from' address as the recipient.
  QString to = _to;
  if ( to.isEmpty() ) {
    to = from;
  }
  kDebug() << "\nFrom:" << from
           << "\nTo:" << to
           << "\nCC:" << cc
           << "\nSubject:" << subject << "\nBody: \n" << body
           << "\nAttachment:\n" << attachment
           << "\nmailTransport: " << mailTransport;

  QTime timer;
  timer.start();

  MailTransport::Transport *transport =
    MailTransport::TransportManager::self()->transportByName( mailTransport );

  if ( !transport ) {
    transport =
      MailTransport::TransportManager::self()->transportByName(
        MailTransport::TransportManager::self()->defaultTransportName() );
  }

  if ( !transport ) {
    kError() << "Error fetching transport; mailTransport"
             << mailTransport << MailTransport::TransportManager::self()->defaultTransportName();
    emit finished( ResultErrorFetchingTransport,
                   i18n( "Error fetching transport. Unable to send invitations" ) );
    return;
  }

  const int transportId = transport->id();

  // gather config values
  KConfig config( QLatin1String( "mailviewerrc" ) );

  KConfigGroup configGroup( &config, QLatin1String( "Invitations" ) );
  const bool outlookConformInvitation = configGroup.readEntry( "LegacyBodyInvites",
#ifdef KDEPIM_ENTERPRISE_BUILD
                                                               true
#else
                                                               false
#endif
                                                             );

  // Now build the message we like to send. The message KMime::Message::Ptr instance
  // will be the root message that has 2 additional message. The body itself and
  // the attached cal.ics calendar file.
  KMime::Message::Ptr message = KMime::Message::Ptr( new KMime::Message );
  message->contentTransferEncoding()->clear();  // 7Bit, decoded.

  // Set the headers

  message->userAgent()->fromUnicodeString(
    KProtocolManager::userAgentForApplication(
      QLatin1String( "KOrganizer" ), QLatin1String( KDEPIMLIBS_VERSION ) ), "utf-8" );

  message->from()->fromUnicodeString( from, "utf-8" );
  message->to()->fromUnicodeString( to, "utf-8" );
  message->cc()->fromUnicodeString( cc, "utf-8" );
  if( bccMe ) {
    message->bcc()->fromUnicodeString( from, "utf-8" ); //from==me, right?
  }
  message->date()->setDateTime( KDateTime::currentLocalDateTime() );
  message->subject()->fromUnicodeString( subject, "utf-8" );

  if ( outlookConformInvitation ) {
    message->contentType()->setMimeType( "text/calendar" );
    message->contentType()->setCharset( "utf-8" );
    message->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
    message->contentType()->setParameter( QLatin1String( "method" ), QLatin1String( "request" ) );

    if ( !attachment.isEmpty() ) {
      KMime::Headers::ContentDisposition *disposition =
        new KMime::Headers::ContentDisposition( message.get() );
      disposition->setDisposition( KMime::Headers::CDinline );
      message->setHeader( disposition );
      message->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
      message->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
    }
  } else {
    // We need to set following 4 lines by hand else KMime::Content::addContent
    // will create a new Content instance for us to attach the main message
    // what we don't need cause we already have the main message instance where
    // 2 additional messages are attached.
    KMime::Headers::ContentType *ct = message->contentType();
    ct->setMimeType( "multipart/mixed" );
    ct->setBoundary( KMime::multiPartBoundary() );
    ct->setCategory( KMime::Headers::CCcontainer );

    // Set the first multipart, the body message.
    KMime::Content *bodyMessage = new KMime::Content;
    KMime::Headers::ContentDisposition *bodyDisposition =
      new KMime::Headers::ContentDisposition( bodyMessage );
    bodyDisposition->setDisposition( KMime::Headers::CDinline );
    bodyMessage->contentType()->setMimeType( "text/plain" );
    bodyMessage->contentType()->setCharset( "utf-8" );
    bodyMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
    bodyMessage->setBody( KMime::CRLFtoLF( body.toUtf8() ) );
    message->addContent( bodyMessage );

    // Set the sedcond multipart, the attachment.
    if ( !attachment.isEmpty() ) {
      KMime::Content *attachMessage = new KMime::Content;
      KMime::Headers::ContentDisposition *attachDisposition =
        new KMime::Headers::ContentDisposition( attachMessage );
      attachDisposition->setDisposition( KMime::Headers::CDattachment );
      attachMessage->contentType()->setMimeType( "text/calendar" );
      attachMessage->contentType()->setCharset( "utf-8" );
      attachMessage->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
      attachMessage->contentType()->setParameter( QLatin1String( "method" ),
                                                  QLatin1String( "request" ) );
      attachMessage->setHeader( attachDisposition );
      attachMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
      attachMessage->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
      message->addContent( attachMessage );
    }
  }

  // Job done, attach the both multiparts and assemble the message.
  message->assemble();

  // Put the newly created item in the MessageQueueJob.
  MailTransport::MessageQueueJob *qjob = new MailTransport::MessageQueueJob( this );
  qjob->transportAttribute().setTransportId( transportId );
  qjob->sentBehaviourAttribute().setSentBehaviour(
           MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection );

  const QString unormalizedFrom = ( transport && transport->specifySenderOverwriteAddress() ) ?
                                                         transport->senderOverwriteAddress() : from;


  const QString normalizedFrom = KPIMUtils::extractEmailAddress(
                                     KPIMUtils::normalizeAddressesAndEncodeIdn( unormalizedFrom ) );

  const QString finalFrom = KPIMUtils::extractEmailAddress( normalizedFrom );
  qjob->addressAttribute().setFrom( finalFrom );

  QStringList toStringList;
  if( !to.isEmpty() ) {
    toStringList = extractEmailAndNormalize( to );
    qjob->addressAttribute().setTo( toStringList );
  }

  QStringList ccStringList;
  if( !cc.isEmpty() ) {
    ccStringList = extractEmailAndNormalize( cc );
    qjob->addressAttribute().setCc( ccStringList );
  }

  QStringList bccStringList;
  if ( bccMe ) {
    bccStringList = extractEmailAndNormalize( from );
    qjob->addressAttribute().setBcc( bccStringList );
  }
  qjob->setMessage( message );
  connect( qjob, SIGNAL(finished(KJob*)), SLOT(handleQueueJobFinished(KJob*)) );
  qjob->start();

#ifdef MAILCLIENTTEST_UNITTEST
  mUnitTestResult.message            = message;
  mUnitTestResult.from               = finalFrom;
  mUnitTestResult.to                 = toStringList;
  mUnitTestResult.cc                 = ccStringList;
  mUnitTestResult.bcc                = bccStringList;
  mUnitTestResult.transportId        = transportId;
#endif
}
예제 #16
0
//From MailClient::send
KMime::Message::Ptr createMessage( const QString &from, const QString &_to,
                                   const QString &cc, const QString &subject,
                                   const QString &body, bool hidden, bool bccMe,
                                   const QString &attachment/*, const QString &mailTransport */)
{
    Q_UNUSED( hidden );

    const bool outlookConformInvitation = false;
    QString userAgent = "libkolab";

    // We must have a recipients list for most MUAs. Thus, if the 'to' list
    // is empty simply use the 'from' address as the recipient.
    QString to = _to;
    if ( to.isEmpty() ) {
        to = from;
    }
    kDebug() << "\nFrom:" << from
             << "\nTo:" << to
             << "\nCC:" << cc
             << "\nSubject:" << subject << "\nBody: \n" << body
             << "\nAttachment:\n" << attachment
             /*<< "\nmailTransport: " << mailTransport*/;

    // Now build the message we like to send. The message KMime::Message::Ptr instance
    // will be the root message that has 2 additional message. The body itself and
    // the attached cal.ics calendar file.
    KMime::Message::Ptr message = KMime::Message::Ptr( new KMime::Message );
    message->contentTransferEncoding()->clear();  // 7Bit, decoded.

    // Set the headers
    message->userAgent()->fromUnicodeString(userAgent, "utf-8" );
    message->from()->fromUnicodeString( from, "utf-8" );
    message->to()->fromUnicodeString( to, "utf-8" );
    message->cc()->fromUnicodeString( cc, "utf-8" );
    if( bccMe ) {
        message->bcc()->fromUnicodeString( from, "utf-8" ); //from==me, right?
    }
    message->date()->setDateTime( KDateTime::currentLocalDateTime() );
    message->subject()->fromUnicodeString( subject, "utf-8" );

    if ( outlookConformInvitation ) {
        message->contentType()->setMimeType( "text/calendar" );
        message->contentType()->setCharset( "utf-8" );
        message->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
        message->contentType()->setParameter( QLatin1String( "method" ), QLatin1String( "request" ) );

        if ( !attachment.isEmpty() ) {
            KMime::Headers::ContentDisposition *disposition =
                new KMime::Headers::ContentDisposition( message.get() );
            disposition->setDisposition( KMime::Headers::CDinline );
            message->setHeader( disposition );
            message->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
            message->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
        }
    } else {
        // We need to set following 4 lines by hand else KMime::Content::addContent
        // will create a new Content instance for us to attach the main message
        // what we don't need cause we already have the main message instance where
        // 2 additional messages are attached.
        KMime::Headers::ContentType *ct = message->contentType();
        ct->setMimeType( "multipart/mixed" );
        ct->setBoundary( KMime::multiPartBoundary() );
        ct->setCategory( KMime::Headers::CCcontainer );

        // Set the first multipart, the body message.
        KMime::Content *bodyMessage = new KMime::Content;
        KMime::Headers::ContentDisposition *bodyDisposition =
            new KMime::Headers::ContentDisposition( bodyMessage );
        bodyDisposition->setDisposition( KMime::Headers::CDinline );
        bodyMessage->contentType()->setMimeType( "text/plain" );
        bodyMessage->contentType()->setCharset( "utf-8" );
        bodyMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
        bodyMessage->setBody( KMime::CRLFtoLF( body.toUtf8() ) );
        message->addContent( bodyMessage );

        // Set the sedcond multipart, the attachment.
        if ( !attachment.isEmpty() ) {
            KMime::Content *attachMessage = new KMime::Content;
            KMime::Headers::ContentDisposition *attachDisposition =
                new KMime::Headers::ContentDisposition( attachMessage );
            attachDisposition->setDisposition( KMime::Headers::CDattachment );
            attachMessage->contentType()->setMimeType( "text/calendar" );
            attachMessage->contentType()->setCharset( "utf-8" );
            attachMessage->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
            attachMessage->contentType()->setParameter( QLatin1String( "method" ),
                    QLatin1String( "request" ) );
            attachMessage->setHeader( attachDisposition );
            attachMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
            attachMessage->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
            message->addContent( attachMessage );
        }
    }

    // Job done, attach the both multiparts and assemble the message.
    message->assemble();
    return message;
}