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

mailcommon

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

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