• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

mailcommon

  • sources
  • kde-4.12
  • kdepim
  • mailcommon
  • filter
mdnadvicedialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2009 Michael Leupold <lemma@confuego.org>
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License along
15  with this program; if not, write to the Free Software Foundation, Inc.,
16  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 
19 #include "mdnadvicedialog.h"
20 #include "kernel/mailkernel.h"
21 
22 #include <messagecore/helpers/messagehelpers.h>
23 #include <messagecore/misc/mdnstateattribute.h>
24 
25 #include <messagecomposer/helper/messagefactory.h>
26 using MessageComposer::MessageFactory;
27 
28 #include <messageviewer/settings/globalsettings.h>
29 #ifndef QT_NO_CURSOR
30 #include <messageviewer/utils/kcursorsaver.h>
31 #endif
32 #include <messageviewer/viewer/objecttreeparser.h>
33 
34 #include <Akonadi/ItemFetchJob>
35 #include <Akonadi/ItemModifyJob>
36 
37 #include <KDebug>
38 #include <KLocale>
39 #include <KMessageBox>
40 
41 #include <QPointer>
42 
43 #include <boost/shared_ptr.hpp>
44 
45 using namespace MailCommon;
46 
47 MDNAdviceHelper *MDNAdviceHelper::s_instance = 0;
48 
49 static const struct {
50  const char * dontAskAgainID;
51  bool canDeny;
52  const char * text;
53 } mdnMessageBoxes[] = {
54  { "mdnNormalAsk", true,
55  I18N_NOOP( "This message contains a request to return a notification "
56  "about your reception of the message.\n"
57  "You can either ignore the request or let the mail program "
58  "send a \"denied\" or normal response." ) },
59  { "mdnUnknownOption", false,
60  I18N_NOOP( "This message contains a request to send a notification "
61  "about your reception of the message.\n"
62  "It contains a processing instruction that is marked as "
63  "\"required\", but which is unknown to the mail program.\n"
64  "You can either ignore the request or let the mail program "
65  "send a \"failed\" response." ) },
66  { "mdnMultipleAddressesInReceiptTo", true,
67  I18N_NOOP( "This message contains a request to send a notification "
68  "about your reception of the message,\n"
69  "but it is requested to send the notification to more "
70  "than one address.\n"
71  "You can either ignore the request or let the mail program "
72  "send a \"denied\" or normal response." ) },
73  { "mdnReturnPathEmpty", true,
74  I18N_NOOP( "This message contains a request to send a notification "
75  "about your reception of the message,\n"
76  "but there is no return-path set.\n"
77  "You can either ignore the request or let the mail program "
78  "send a \"denied\" or normal response." ) },
79  { "mdnReturnPathNotInReceiptTo", true,
80  I18N_NOOP( "This message contains a request to send a notification "
81  "about your reception of the message,\n"
82  "but the return-path address differs from the address "
83  "the notification was requested to be sent to.\n"
84  "You can either ignore the request or let the mail program "
85  "send a \"denied\" or normal response." ) },
86 };
87 
88 static const int numMdnMessageBoxes =
89  sizeof mdnMessageBoxes / sizeof *mdnMessageBoxes;
90 
91 MDNAdviceDialog::MDNAdviceDialog( const QString &text, bool canDeny, QWidget *parent )
92  : KDialog( parent ), m_result( MessageComposer::MDNIgnore )
93 {
94  setCaption( i18n( "Message Disposition Notification Request" ) );
95  if ( canDeny ) {
96  setButtons( KDialog::Yes | KDialog::User1 | KDialog::User2 );
97  setButtonText( KDialog::User2, i18n( "Send \"&denied\"" ) );
98  } else {
99  setButtons( KDialog::Yes | KDialog::User1 );
100  }
101  setButtonText( KDialog::Yes, i18n( "&Ignore" ) );
102  setButtonText( KDialog::User1, i18n( "&Send" ) );
103  setEscapeButton( KDialog::Yes );
104  KMessageBox::createKMessageBox(
105  this,
106  QMessageBox::Question,
107  text,
108  QStringList(),
109  QString(),
110  0,
111  KMessageBox::NoExec );
112 }
113 
114 MDNAdviceDialog::~MDNAdviceDialog()
115 {
116 }
117 
118 MessageComposer::MDNAdvice MDNAdviceDialog::result() const
119 {
120  return m_result;
121 }
122 
123 MessageComposer::MDNAdvice MDNAdviceHelper::questionIgnoreSend( const QString &text, bool canDeny )
124 {
125  MessageComposer::MDNAdvice rc = MessageComposer::MDNIgnore;
126  QPointer<MDNAdviceDialog> dlg( new MDNAdviceDialog( text, canDeny ) );
127  dlg->exec();
128  if ( dlg ) {
129  rc = dlg->result();
130  }
131  delete dlg;
132  return rc;
133 }
134 
135 QPair< bool, KMime::MDN::SendingMode > MDNAdviceHelper::checkAndSetMDNInfo(
136  const Akonadi::Item &item, KMime::MDN::DispositionType d, bool forceSend )
137 {
138  KMime::Message::Ptr msg = MessageCore::Util::message( item );
139 
140  // RFC 2298: At most one MDN may be issued on behalf of each
141  // particular recipient by their user agent. That is, once an MDN
142  // has been issued on behalf of a recipient, no further MDNs may be
143  // issued on behalf of that recipient, even if another disposition
144  // is performed on the message.
145  if ( item.hasAttribute< MessageCore::MDNStateAttribute >() &&
146  item.attribute< MessageCore::MDNStateAttribute >()->mdnState() != MessageCore::MDNStateAttribute::MDNStateUnknown ) {
147  // if already dealt with, don't do it again.
148  return QPair< bool, KMime::MDN::SendingMode >( false, KMime::MDN::SentAutomatically );
149  }
150  MessageCore::MDNStateAttribute *mdnStateAttr =
151  new MessageCore::MDNStateAttribute( MessageCore::MDNStateAttribute::MDNStateUnknown );
152 
153  KMime::MDN::SendingMode s = KMime::MDN::SentAutomatically; // set to manual if asked user
154  bool doSend = false;
155  // default:
156  int mode = MessageViewer::GlobalSettings::self()->defaultPolicy();
157  if ( forceSend ) { //We must send it
158  mode = 3;
159  } else {
160  if ( !mode || mode < 0 || mode > 3 ) {
161  // early out for ignore:
162  mdnStateAttr->setMDNState( MessageCore::MDNStateAttribute::MDNIgnore );
163  s = KMime::MDN::SentManually;
164  } else {
165 
166  if ( MessageFactory::MDNMDNUnknownOption( msg ) ) {
167  mode = requestAdviceOnMDN( "mdnUnknownOption" );
168  s = KMime::MDN::SentManually;
169  // TODO set type to Failed as well
170  // and clear modifiers
171  }
172 
173  if ( MessageFactory::MDNConfirmMultipleRecipients( msg ) ) {
174  mode = requestAdviceOnMDN( "mdnMultipleAddressesInReceiptTo" );
175  s = KMime::MDN::SentManually;
176  }
177 
178  if ( MessageFactory::MDNReturnPathEmpty( msg ) ) {
179  mode = requestAdviceOnMDN( "mdnReturnPathEmpty" );
180  s = KMime::MDN::SentManually;
181  }
182 
183  if ( MessageFactory::MDNReturnPathNotInRecieptTo( msg ) ) {
184  mode = requestAdviceOnMDN( "mdnReturnPathNotInReceiptTo" );
185  s = KMime::MDN::SentManually;
186  }
187 
188  if ( MessageFactory::MDNRequested( msg ) ) {
189  if ( s != KMime::MDN::SentManually ) {
190  // don't ask again if user has already been asked. use the users' decision
191  mode = requestAdviceOnMDN( "mdnNormalAsk" );
192  s = KMime::MDN::SentManually; // asked user
193  }
194  } else { // if message doesn't have a disposition header, never send anything.
195  mode = 0;
196  }
197 
198  }
199  }
200 
201  // RFC 2298: An MDN MUST NOT be generated in response to an MDN.
202  if ( MessageViewer::ObjectTreeParser::findType( msg.get(),
203  "message",
204  "disposition-notification",
205  true, true ) ) {
206  mdnStateAttr->setMDNState( MessageCore::MDNStateAttribute::MDNIgnore );
207  } else if ( mode == 0 ) { // ignore
208  doSend = false;
209  mdnStateAttr->setMDNState( MessageCore::MDNStateAttribute::MDNIgnore );
210  } else if ( mode == 2 ) { // denied
211  doSend = true;
212  mdnStateAttr->setMDNState( MessageCore::MDNStateAttribute::MDNDenied );
213  } else if ( mode == 3 ) { // the user wants to send. let's make sure we can, according to the RFC.
214  doSend = true;
215  mdnStateAttr->setMDNState( dispositionToSentState( d ) );
216  }
217 
218  // create a minimal version of item with just the attribute we want to change
219  Akonadi::Item i( item.id() );
220  i.setRevision( item.revision() );
221  i.setMimeType( item.mimeType() );
222  i.addAttribute( mdnStateAttr );
223  Akonadi::ItemModifyJob *modify = new Akonadi::ItemModifyJob( i );
224  modify->setIgnorePayload( true );
225  modify->disableRevisionCheck();
226  return QPair< bool, KMime::MDN::SendingMode >( doSend, s );
227 }
228 
229 MessageCore::MDNStateAttribute::MDNSentState MDNAdviceHelper::dispositionToSentState(
230  KMime::MDN::DispositionType d )
231 {
232  switch ( d ) {
233  case KMime::MDN::Displayed:
234  return MessageCore::MDNStateAttribute::MDNDisplayed;
235  case KMime::MDN::Deleted:
236  return MessageCore::MDNStateAttribute::MDNDeleted;
237  case KMime::MDN::Dispatched:
238  return MessageCore::MDNStateAttribute::MDNDispatched;
239  case KMime::MDN::Processed:
240  return MessageCore::MDNStateAttribute::MDNProcessed;
241  case KMime::MDN::Denied:
242  return MessageCore::MDNStateAttribute::MDNDenied;
243  case KMime::MDN::Failed:
244  return MessageCore::MDNStateAttribute::MDNFailed;
245  default:
246  return MessageCore::MDNStateAttribute::MDNStateUnknown;
247  };
248 }
249 
250 int MDNAdviceHelper::requestAdviceOnMDN( const char *what )
251 {
252  for ( int i = 0; i < numMdnMessageBoxes; ++i ) {
253  if ( !qstrcmp( what, mdnMessageBoxes[i].dontAskAgainID ) ) {
254 #ifndef QT_NO_CURSOR
255  const MessageViewer::KCursorSaver saver( Qt::ArrowCursor );
256 #endif
257  MessageComposer::MDNAdvice answer;
258  answer = questionIgnoreSend( i18n( mdnMessageBoxes[i].text ),
259  mdnMessageBoxes[i].canDeny );
260  switch ( answer ) {
261  case MessageComposer::MDNSend:
262  return 3;
263 
264  case MessageComposer::MDNSendDenied:
265  return 2;
266 
267  // don't use 1, as that's used for 'default ask" in checkMDNHeaders
268  default:
269  case MessageComposer::MDNIgnore:
270  return 0;
271  }
272  }
273  }
274  kWarning() << "didn't find data for message box \"" << what << "\"";
275  return MessageComposer::MDNIgnore;
276 }
277 
278 void MDNAdviceDialog::slotButtonClicked( int button )
279 {
280  switch ( button ) {
281  case KDialog::User1:
282  m_result = MessageComposer::MDNSend;
283  accept();
284  break;
285 
286  case KDialog::User2:
287  m_result = MessageComposer::MDNSendDenied;
288  accept();
289  break;
290 
291  case KDialog::Yes:
292  default:
293  m_result = MessageComposer::MDNIgnore;
294  accept();
295  break;
296 
297  }
298  reject();
299 }
300 
301 #include "mdnadvicedialog.moc"
MailCommon::MDNAdviceDialog::result
MessageComposer::MDNAdvice result() const
Definition: mdnadvicedialog.cpp:118
mdnMessageBoxes
static const struct @0 mdnMessageBoxes[]
MailCommon::MDNAdviceDialog
Definition: mdnadvicedialog.h:77
MailCommon::MDNAdviceDialog::slotButtonClicked
void slotButtonClicked(int button)
Definition: mdnadvicedialog.cpp:278
MailCommon::MDNAdviceDialog::~MDNAdviceDialog
~MDNAdviceDialog()
Definition: mdnadvicedialog.cpp:114
text
const char * text
Definition: mdnadvicedialog.cpp:52
QWidget
MailCommon::MDNAdviceHelper::dispositionToSentState
MessageCore::MDNStateAttribute::MDNSentState dispositionToSentState(KMime::MDN::DispositionType d)
Definition: mdnadvicedialog.cpp:229
KDialog
canDeny
bool canDeny
Definition: mdnadvicedialog.cpp:51
mdnadvicedialog.h
MailCommon::MDNAdviceHelper
Definition: mdnadvicedialog.h:32
MailCommon::MDNAdviceHelper::checkAndSetMDNInfo
QPair< bool, KMime::MDN::SendingMode > checkAndSetMDNInfo(const Akonadi::Item &item, KMime::MDN::DispositionType d, bool forceSend=false)
Checks the MDN headers to see if the user needs to be asked for any confirmations.
Definition: mdnadvicedialog.cpp:135
numMdnMessageBoxes
static const int numMdnMessageBoxes
Definition: mdnadvicedialog.cpp:88
MailCommon::MDNAdviceDialog::MDNAdviceDialog
MDNAdviceDialog(const QString &text, bool canDeny, QWidget *parent=0)
Definition: mdnadvicedialog.cpp:91
mailkernel.h
dontAskAgainID
const char * dontAskAgainID
Definition: mdnadvicedialog.cpp:50
I18N_NOOP
#define I18N_NOOP(t)
Definition: searchpatternedit.cpp:46
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:55:15 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

mailcommon

Skip menu "mailcommon"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal