Framework for looking up contacts directly in nepomuk in addition to going through...
[kdepim.git] / messagecomposer / messagehelper.cpp
blob5a6ee0133c2794ce86393ba393bdfe6de52dd6f7
1 /* -*- mode: C++; c-file-style: "gnu" -*-
2 Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
3 Copyright (c) 2009 Andras Mantia <andras@kdab.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "messagehelper.h"
21 #include "kdepim-version.h"
22 #include "util.h"
23 #include "messagecomposersettings.h"
25 #include "messagecore/mailinglist.h"
26 #include "messagecore/stringutil.h"
28 #include <KDateTime>
29 #include <KProtocolManager>
30 #include <KMime/Message>
31 #include <kmime/kmime_mdn.h>
32 #include <kmime/kmime_dateformatter.h>
33 #include <kmime/kmime_headers.h>
34 #include <kpimidentities/identitymanager.h>
35 #include <kpimidentities/identity.h>
36 #include <KPIMUtils/Email>
38 using namespace MessageCore;
40 namespace MessageHelper {
42 void initHeader( const KMime::Message::Ptr &message, const KPIMIdentities::IdentityManager* identMan, uint id )
44 applyIdentity( message, identMan, id );
45 message->to()->clear();
46 message->subject()->clear();
47 message->date()->setDateTime( KDateTime::currentLocalDateTime() );
49 // user agent, e.g. KMail/1.9.50 (Windows/5.0; KDE/3.97.1; i686; svn-762186; 2008-01-15)
50 QStringList extraInfo;
51 #if defined KDEPIM_GIT_REVISION_STRING && defined KDEPIM_GIT_LAST_CHANGE
52 extraInfo << QString::fromLocal8Bit(KDEPIM_GIT_REVISION_STRING) << QString::fromLocal8Bit(KDEPIM_GIT_LAST_CHANGE);
53 #else
54 #error forgot to include kdepim-version.h
55 #endif
57 message->userAgent()->fromUnicodeString( KProtocolManager::userAgentForApplication( QString::fromLocal8Bit("KMail"), QString::fromLocal8Bit(KDEPIM_GIT_REVISION_STRING), extraInfo ), QLatin1String("utf-8").latin1() );
58 // This will allow to change Content-Type:
59 message->contentType()->setMimeType( "text/plain" );
64 void initFromMessage( const KMime::Message::Ptr &msg, const KMime::Message::Ptr &origMsg,
65 KPIMIdentities::IdentityManager* identMan, uint id, bool idHeaders )
67 if ( idHeaders )
68 MessageHelper::initHeader( msg, identMan, id );
69 else {
70 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Identity", msg.get(),
71 QString::number( id ), "utf-8" );
72 msg->setHeader( header );
75 if ( origMsg->headerByType("X-KMail-Transport") ) {
76 const QString transport = origMsg->headerByType("X-KMail-Transport")->asUnicodeString();
77 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Transport", msg.get(),
78 transport, "utf-8" );
79 msg->setHeader( header );
84 void applyIdentity( const KMime::Message::Ptr &message, const KPIMIdentities::IdentityManager* identMan, uint id )
86 const KPIMIdentities::Identity & ident =
87 identMan->identityForUoidOrDefault( id );
89 if ( ident.fullEmailAddr().isEmpty() )
90 message->from()->clear();
91 else
92 message->from()->addAddress(ident.primaryEmailAddress().toUtf8(), ident.fullName());
94 if ( ident.replyToAddr().isEmpty() )
95 message->replyTo()->clear();
96 else
97 message->replyTo()->addAddress(ident.primaryEmailAddress().toUtf8(), ident.fullName());
99 if ( ident.bcc().isEmpty() )
100 message->bcc()->clear();
101 else {
102 const KMime::Types::Mailbox::List mailboxes = MessageCore::StringUtil::mailboxListFromUnicodeString( ident.bcc() );
103 foreach ( const KMime::Types::Mailbox &mailbox, mailboxes )
104 message->bcc()->addAddress( mailbox );
107 if ( ident.organization().isEmpty() )
108 message->removeHeader("Organization");
109 else {
110 KMime::Headers::Organization * const organization
111 = new KMime::Headers::Organization( message.get(), ident.organization(), "utf-8" );
112 message->setHeader( organization );
115 if (ident.isDefault())
116 message->removeHeader("X-KMail-Identity");
117 else {
118 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Identity", message.get(), QString::number( ident.uoid() ), "utf-8" );
119 message->setHeader( header );
122 if (ident.transport().isEmpty())
123 message->removeHeader("X-KMail-Transport");
124 else {
125 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Transport", message.get(), ident.transport(), "utf-8" );
126 message->setHeader( header );
129 if (ident.fcc().isEmpty())
130 message->removeHeader("X-KMail-Fcc");
131 else {
132 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Fcc", message.get(), ident.fcc(), "utf-8" );
133 message->setHeader( header );
136 if (ident.drafts().isEmpty())
137 message->removeHeader("X-KMail-Drafts");
138 else {
139 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Drafts", message.get(), ident.drafts(), "utf-8" );
140 message->setHeader( header );
143 if (ident.templates().isEmpty())
144 message->removeHeader("X-KMail-Templates");
145 else {
146 KMime::Headers::Generic *header = new KMime::Headers::Generic( "X-KMail-Templates", message.get(), ident.templates(), "utf-8" );
147 message->setHeader( header );
151 KMime::Types::AddrSpecList extractAddrSpecs( const KMime::Message::Ptr &msg, const QByteArray & header )
153 KMime::Types::AddrSpecList result;
154 if ( !msg->headerByType( header ) )
155 return result;
157 KMime::Types::AddressList al =
158 MessageCore::StringUtil::splitAddressField( msg->headerByType( header )->asUnicodeString().toUtf8() );
159 KMime::Types::AddressList::const_iterator alend( al.constEnd() );
160 for ( KMime::Types::AddressList::const_iterator ait = al.constBegin() ; ait != alend ; ++ait ) {
161 KMime::Types::MailboxList::const_iterator mitEnd( (*ait).mailboxList.constEnd() );
162 for ( KMime::Types::MailboxList::const_iterator mit = (*ait).mailboxList.constBegin() ; mit != mitEnd ; ++mit ) {
163 result.push_back( (*mit).addrSpec() );
166 return result;
169 QString cleanSubject( const KMime::Message::Ptr &msg )
171 return cleanSubject( msg, MessageComposer::MessageComposerSettings::self()->replyPrefixes() + MessageComposer::MessageComposerSettings::self()->forwardPrefixes(),
172 true, QString() ).trimmed();
175 QString cleanSubject( const KMime::Message::Ptr &msg, const QStringList & prefixRegExps,
176 bool replace, const QString & newPrefix )
178 return replacePrefixes( msg->subject()->asUnicodeString(), prefixRegExps, replace,
179 newPrefix );
182 QString forwardSubject( const KMime::Message::Ptr &msg )
184 return cleanSubject( msg, MessageComposer::MessageComposerSettings::self()->forwardPrefixes(),
185 MessageComposer::MessageComposerSettings::self()->replaceForwardPrefix(), QString::fromLatin1("Fwd:") );
188 QString replySubject( const KMime::Message::Ptr &msg )
190 return cleanSubject( msg, MessageComposer::MessageComposerSettings::self()->replyPrefixes(),
191 MessageComposer::MessageComposerSettings::self()->replaceReplyPrefix(), QString::fromLatin1("Re:") );
194 QString replacePrefixes( const QString& str, const QStringList &prefixRegExps,
195 bool replace, const QString &newPrefix )
197 bool recognized = false;
198 // construct a big regexp that
199 // 1. is anchored to the beginning of str (sans whitespace)
200 // 2. matches at least one of the part regexps in prefixRegExps
201 QString bigRegExp = QString::fromLatin1("^(?:\\s+|(?:%1))+\\s*")
202 .arg( prefixRegExps.join(QString::fromLatin1(")|(?:")) );
203 QRegExp rx( bigRegExp, Qt::CaseInsensitive );
204 if ( rx.isValid() ) {
205 QString tmp = str;
206 if ( rx.indexIn( tmp ) == 0 ) {
207 recognized = true;
208 if ( replace )
209 return tmp.replace( 0, rx.matchedLength(), newPrefix + QString::fromLatin1( " " ) );
211 } else {
212 kWarning() << "bigRegExp = \""
213 << bigRegExp << "\"\n"
214 << "prefix regexp is invalid!";
215 // try good ole Re/Fwd:
216 recognized = str.startsWith( newPrefix );
219 if ( !recognized )
220 return newPrefix + QString::fromLatin1(" ") + str;
221 else
222 return str;
226 void setAutomaticFields(const KMime::Message::Ptr &msg, bool aIsMulti)
228 msg->setHeader( new KMime::Headers::Generic( "MIME-Version", msg.get(), QLatin1String("1.0"), QLatin1String("utf-8").latin1() ) );
230 if (aIsMulti || msg->contents().size() > 1)
232 // Set the type to 'Multipart' and the subtype to 'Mixed'
233 msg->contentType()->setMimeType( "multipart/mixed" );
234 // Create a random printable string and set it as the boundary parameter
235 msg->contentType()->setBoundary( KMime::multiPartBoundary() );
239 QString ccStrip( const KMime::Message::Ptr &msg )
241 return MessageCore::StringUtil::stripEmailAddr( msg->cc()->asUnicodeString() );
244 QString toStrip( const KMime::Message::Ptr &msg )
246 return MessageCore::StringUtil::stripEmailAddr( msg->to()->asUnicodeString() );
249 QString fromStrip( const KMime::Message::Ptr &msg )
251 return MessageCore::StringUtil::stripEmailAddr( msg->from()->asUnicodeString() );
255 QString stripOffPrefixes( const QString& str )
257 return replacePrefixes( str, MessageComposer::MessageComposerSettings::self()->replyPrefixes() + MessageComposer::MessageComposerSettings::self()->forwardPrefixes(),
258 true, QString() ).trimmed();
261 QString skipKeyword( const QString& aStr, QChar sepChar,
262 bool* hasKeyword)
264 QString str = aStr;
266 while (str[0] == QChar::fromLatin1(' ')) str.remove(0,1);
267 if (hasKeyword) *hasKeyword=false;
269 unsigned int i = 0, maxChars = 3;
270 unsigned int strLength(str.length());
271 for (i=0; i < strLength && i < maxChars; i++)
273 if (str[i] < QChar::fromLatin1('A') || str[i] == sepChar) break;
276 if (str[i] == sepChar) // skip following spaces too
278 do {
279 i++;
280 } while (str[i] == QChar::fromLatin1(' '));
281 if (hasKeyword) *hasKeyword=true;
282 return str.mid(i);
284 return str;