2 * Copyright (C) 2006 Dmitry Morozhnikov <dmiceman@mail.ru>
3 * Copyright (C) 2011 Sudhendu Kumar <sudhendu.kumar.roy@gmail.com>
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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #ifndef TEMPLATEPARSER_TEMPLATEPARSER_H
22 #define TEMPLATEPARSER_TEMPLATEPARSER_H
24 #include "templateparser_export.h"
26 #include <messageviewer/viewer/objecttreeemptysource.h>
28 #include <Akonadi/Collection>
29 #include <KMime/KMimeMessage>
33 namespace MessageViewer
{
34 class ObjectTreeParser
;
37 namespace KPIMIdentities
{
38 class IdentityManager
;
41 namespace MessageCore
{
42 class AttachmentCollector
;
46 namespace TemplateParser
{
49 * \brief The TemplateParser transforms a message with a given template.
52 * The TemplateParser transforms a message with a given template.
53 * A template contains text and commands, such as %QUOTE or %ODATE, which will be
54 * replaced with the real values in process().
57 * The message given in the templateparser constructor amsg, is the message that
58 * is being transformed.
59 * aorig_msg is the original message to which actions are performed.
60 * The message text in amsg will be replaced by the processed text of the template,
61 * but other properties, such as the attachments or the subject, are preserved.
63 * There are two different kind of commands: Those that work on the message that is
64 * to be transformed and those that work on an 'original message'.
65 * Those that work on the message that is to be transformed have no special prefix, e.g.
66 * '%DATE'. Those that work on the original message have an 'O' prefix, for example
68 * This means that the %DATE command will take the date of the message passed in the
69 * constructor, the message which is to be transformed, whereas the %ODATE command will
70 * take the date of the message that is being passed in process(), the original message.
73 * The process() function takes aorig_msg as parameter. This aorig_msg is the original
74 * message from which various commands in templates with prefix 'O' extract the data and adds
75 * to the processed message.
76 * This function finds the template and passes them to processWithTemplate(), where templates
77 * are processed and its value is added to the processed message.
79 * \par Reply To/Forward Plain Text Mails
80 * Plain Text mails are the mails with only text part and no html part. While creating
81 * reply/forward to mails, processWithTemplate() processes all the commands and then
82 * appends its values to plainBody and htmlBody. This function then on the
83 * basis of whether the user wants to use plain mails or HTML mails, clears the htmlBody,
84 * or just passes both the plainBody and htmlBody unaltered.
86 * \par Reply To/Forward HTML Mails
87 * By HTML mails here, we mean multipart/alternative mails. As mentioned above, all
88 * commands in the TemplateParser appends text, i.e. plain text to plainBody
89 * and html text to htmlBody in the function processWithTemplate().
90 * This function also takes a decision of clearing the htmlBody on the basis of fact
91 * whether the user wants to reply/forward using plain mails or multipart/alternative
94 * \par When "TO" and when "NOT TO" make multipart/alternative Mails
95 * User is the master to decide when to and when not to make multipart/alternative mails.
96 * <b>For user who <u>don't prefer</u> using HTML mails</b>
97 * There is a GlobalSettings::self()->replyUsingHtml() (in GUI as Settings->Configure KMail->
98 * Composer->General->"Reply using HTML if present"), which when not true (checkbox disabled
99 * in UI), will clear the htmlBody.
100 * An another option within the standard templates, %FORCEDPLAIN command raises the flag,
101 * ReplyAsPlain. This flag when raised in processWithTemplate() takes care that the
102 * processed message will contain text/plain part by clearing the htmlBody.
104 * Once the htmlBody is cleared, plainBody and an empty htmlBody is passed to
105 * addProcessedBodyToMessage(). Here since the htmlBody is empty, text/plain messages are
106 * assembled and thus user is not dealing with any kind of HTML part.
108 * <b>For user who <u>do prefer</u> using HTML mails</b>
109 * The setting discussed above as "Reply using HTML if present" (when checked to true),
110 * passes the htmlBody to addProcessedBodyToMessage() without doing any changes.
111 * An another option %FORCEDHTML within standard templates command raises the flag ReplyAsHtml.
112 * This flag when raised in processWithTemplate() takes care that the htmlBody is passed to
113 * addProcessedBodyToMessage() unaltered.
115 * Since htmlBody received by addProcessedBodyToMessage() is not empty, multipart/alternative
116 * messages are assembled.
118 * @NOTE Resolving conflict between GlobalSettings "replyUsingHtml" and FORCEDXXXX command.
119 * The conflict is resolved by simply giving preference to the commands over GlobalSettings.
121 * \par Make plain part
122 * mMsg is the reply message in which the message text will be replaced by the
123 * processed value from templates.
125 * In case of no attachments, the message will be a single-part message.
126 * A KMime::Content containing the plainBody from processWithTemplate() is
127 * created. Then the encodedBody(), contentType (text/plain) of this
128 * KMime::Content is set in the body and the header of mMsg. The addContent()
129 * method can be used for adding sub-content to content object in case of
130 * attachments. The addContent() method is not used for adding content of the
131 * above mentioned single-part, as addContent() will convert single-part to
132 * multipart-mixed before adding it to mMsg.
134 * \par Make multipart/alternative mails
135 * First of all a KMime::Content (content) is created with a content-type of
136 * multipart/alternative. Then in the same way as plain-part is created in above
137 * paragraph, a KMime::Content (sub-content) containing the plainBody is created
138 * and added as child to the content. Then a new KMime::Content (sub-content)
139 * with htmlBody as the body is created. The content-type is set as text/html.
140 * This new sub-content is then added to the parent content. Now, since the
141 * parent content (multipart/alternative) has two sub-content (text/plain and
142 * text/html) to it, it is added to the reply message (mMsg).
144 * TODO: What is the usecase of the commands that work on the message to be transformed?
145 * In general you only use the commands that work on the original message...
147 class TEMPLATEPARSER_EXPORT TemplateParser
: public QObject
159 enum AllowSelection
{
165 ReplyAsOriginalMessage
,
171 explicit TemplateParser( const KMime::Message::Ptr
&amsg
, const Mode amode
);
175 * Sets the selection. If this is set, only the selection will be added to
176 * commands such as %QUOTE. Otherwise, the whole message is quoted.
177 * If this is not called at all, the whole message is quoted as well.
178 * Call this before calling process().
180 void setSelection( const QString
&selection
);
183 * Sets whether the template parser is allowed to decrypt the original
184 * message when needing its message text, for example for the %QUOTE command.
185 * If true, it will tell the ObjectTreeParser it uses internally to decrypt the
186 * message, and that will possibly show a password request dialog to the user.
188 * The default is false.
190 void setAllowDecryption( const bool allowDecryption
);
193 * Tell template parser whether or not to wrap words, and at what column
196 * Default is true, wrapping at 80chars.
198 void setWordWrap( bool wrap
, int wrapColWidth
= 80 );
201 * Set the identity manager to be used when creating the template.
203 void setIdentityManager( KPIMIdentities::IdentityManager
*ident
);
206 * Sets the list of charsets to try to use to encode the resulting text.
207 * They are tried in order until one matches, or utf-8 as a fallback.
209 void setCharsets( const QStringList
&charsets
);
211 virtual void process( const KMime::Message::Ptr
&aorig_msg
,
212 const Akonadi::Collection
&afolder
= Akonadi::Collection() );
213 virtual void process( const QString
&tmplName
, const KMime::Message::Ptr
&aorig_msg
,
214 const Akonadi::Collection
&afolder
= Akonadi::Collection() );
215 virtual void processWithIdentity( uint uoid
, const KMime::Message::Ptr
&aorig_msg
,
216 const Akonadi::Collection
&afolder
= Akonadi::Collection() );
218 virtual void processWithTemplate( const QString
&tmpl
);
220 /// This finds the template to use. Either the one from the folder, identity or
221 /// finally the global template.
222 /// This also reads the To and CC address of the template
223 /// @return the contents of the template
224 virtual QString
findTemplate();
226 /// Finds the template with the given name.
227 /// This also reads the To and CC address of the template
228 /// @return the contents of the template
229 virtual QString
findCustomTemplate( const QString
&tmpl
);
231 virtual QString
pipe( const QString
&cmd
, const QString
&buf
);
233 virtual QString
getFName( const QString
&str
);
234 virtual QString
getLName( const QString
&str
);
236 bool cursorPositionWasSet() const;
239 Akonadi::Collection mFolder
; //Used to find a template
241 KMime::Message::Ptr mMsg
; // Msg to write to
242 KMime::Message::Ptr mOrigMsg
; // Msg to read from
244 bool mAllowDecryption
;
246 QString mQuoteString
;
248 KPIMIdentities::IdentityManager
*m_identityManager
;
251 QStringList m_charsets
;
252 AllowSelection isSelectionAllowed
;
253 MessageViewer::ObjectTreeParser
*mOtp
;
254 MessageViewer::EmptySource
*mEmptySource
;
255 QString mHeadElement
;
257 bool mForceCursorPosition
;
260 * Called by processWithTemplate(). This adds the completely processed body to
263 * This function creates plain text message or multipart/alternative message,
264 * depending on whether the processed body has @p htmlBody or not.
266 * In append mode, this will simply append the text to the body.
268 * Otherwise, the content of the old message is deleted and replaced with @p plainBody
270 * Attachments of the original message are also added back to the new message.
272 void addProcessedBodyToMessage( const QString
&plainBody
, const QString
&htmlBody
) const;
275 * Determines whether the signature should be stripped when getting the text
276 * of the original message, e.g. for commands such as %QUOTE
278 bool shouldStripSignature() const;
280 int parseQuotes( const QString
&prefix
, const QString
&str
, QString
"e
) const;
284 * Return the text signature used the by current identity.
286 QString
getPlainSignature() const;
289 * Return the HTML signature used the by current identity.
291 QString
getHtmlSignature() const;
294 * Returns message body indented by the
295 * given indentation string. This is suitable for including the message
296 * in another message of for replies, forwards.
298 * No attachments are handled if includeAttach is false.
299 * The signature is stripped if aStripSignature is true and
300 * smart quoting is turned on. Signed or encrypted texts
301 * get converted to plain text when allowDecryption is true.
303 QString
quotedPlainText( const QString
& election
=QString() ) const;
306 * Returns HTML message body.
307 * This is suitable for including the message
308 * in another message of for replies, forwards.
310 * No attachments are handled if includeAttach is false.
311 * The signature is stripped if aStripSignature is true and
312 * smart quoting is turned on. Signed or encrypted texts
313 * get converted to plain text when allowDecryption is true.
315 QString
quotedHtmlText( const QString
&selection
) const;
318 * This function return the plain text part from the OTP.
319 * For HTML only mails. It returns the converted plain text
321 * @param allowSelectionOnly takes care that if a reply/forward
322 * is made to a selected part of message, then the selection is
323 * returned as it is without going through th OTP
324 * @param aStripSignature strips the signature out of the message
327 QString
plainMessageText( bool aStripSignature
, AllowSelection isSelectionAllowed
) const;
330 * Returns the HTML content of the message as plain text
332 QString
htmlMessageText( bool aStripSignature
, AllowSelection isSelectionAllowed
);
334 /** @return the UOID of the identity for this message.
335 * Searches the "x-kmail-identity" header and if that fails,
336 * searches with KPIMIdentities::IdentityManager::identityForAddress()
338 uint
identityUoid( const KMime::Message::Ptr
&msg
) const;
341 * Returns KMime content of the plain text part of the message after setting
342 * its mime type, charset and CTE.
343 * This function is called by:-
344 * 1) TemplateParser::addProcessedBodyToMessage(), which uses this content
345 * to simply create the text/plain message
347 * 2) TemplateParser::createMultipartAlternativeContent() which adds this content
348 * to create the multipart/alternative message.
350 KMime::Content
*createPlainPartContent( const QString
&plainBody
) const;
353 * Returns KMime content of the multipart/alternative part of the message
354 * after setting the mime type, charset and CTE of its respective text/plain
355 * part and text/html part.
357 KMime::Content
*createMultipartAlternativeContent( const QString
&plainBody
,
358 const QString
&htmlBody
) const;
361 * Returns a multipart/mixed KMime::Content that has textPart and all
362 * attachments as children.
363 * @param ac a reference to an MessageCore::AttachmentCollector that has
364 * collected all attachments.
365 * @param textPart a KMime::Content that is to be added as a child.
368 KMime::Content
*createMultipartMixed( const MessageCore::AttachmentCollector
&ac
,
369 KMime::Content
*textPart
) const;
372 * Returnsa multipart/related KMime::Content that has mainTextPart and all
373 * embedded images as children.
374 * @param ac a reference to an MessageCore::ImageCollector that has
375 * collected all attachments.
376 * @param mainTextPart a KMime::Content that is to be added as a child.
379 KMime::Content
*createMultipartRelated( const MessageCore::ImageCollector
&ic
,
380 KMime::Content
*mainTextPart
) const;
383 * Checks if the signature is HTML or not.
385 bool isHtmlSignature() const;
388 * Does the necessary conversions like escaping charecters, changing "\n" to
389 * breakline tag before appending text to htmlBody.
391 QString
plainToHtml( const QString
&body
) const;
394 * Make a HTML content valid by adding missing html/head/body tag.
396 void makeValidHtml( QString
&body
);