KMime

kmime_mdn.cpp
Go to the documentation of this file.
1 /* -*- c++ -*-
2  kmime_mdn.cpp
3 
4  KMime, the KDE Internet mail/usenet news message library.
5  Copyright (c) 2002 Marc Mutz <[email protected]>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
34 #include "kmime_mdn.h"
35 #include "kmime_version.h"
36 #include "kmime_util.h"
37 #include "kmime_codecs.h"
38 #include "kmime_debug.h"
39 
40 #include <KLocalizedString>
41 
42 #include <QByteArray>
43 
44 #ifdef Q_OS_WIN // gethostname
45 # include <winsock2.h>
46 #else
47 # include <unistd.h>
48 #endif
49 
50 namespace KMime
51 {
52 
53 namespace MDN
54 {
55 
56 static const struct {
57  DispositionType dispositionType;
58  const char *string;
59  const char *description;
60 } dispositionTypes[] = {
61  {
62  Displayed, "displayed",
63  I18N_NOOP("The message sent on ${date} to ${to} with subject "
64  "\"${subject}\" has been displayed. This is no guarantee that "
65  "the message has been read or understood.")
66  },
67  {
68  Deleted, "deleted",
69  I18N_NOOP("The message sent on ${date} to ${to} with subject "
70  "\"${subject}\" has been deleted unseen. This is no guarantee "
71  "that the message will not be \"undeleted\" and nonetheless "
72  "read later on.")
73  },
74  {
75  Dispatched, "dispatched",
76  I18N_NOOP("The message sent on ${date} to ${to} with subject "
77  "\"${subject}\" has been dispatched. This is no guarantee "
78  "that the message will not be read later on.")
79  },
80  {
81  Processed, "processed",
82  I18N_NOOP("The message sent on ${date} to ${to} with subject "
83  "\"${subject}\" has been processed by some automatic means.")
84  },
85  {
86  Denied, "denied",
87  I18N_NOOP("The message sent on ${date} to ${to} with subject "
88  "\"${subject}\" has been acted upon. The sender does not wish "
89  "to disclose more details to you than that.")
90  },
91  {
92  Failed, "failed",
93  I18N_NOOP("Generation of a Message Disposition Notification for the "
94  "message sent on ${date} to ${to} with subject \"${subject}\" "
95  "failed. Reason is given in the Failure: header field below.")
96  }
97 };
98 
99 static const int numDispositionTypes =
100  sizeof dispositionTypes / sizeof *dispositionTypes;
101 
102 static const char *stringFor(DispositionType d)
103 {
104  for (int i = 0 ; i < numDispositionTypes ; ++i) {
105  if (dispositionTypes[i].dispositionType == d) {
106  return dispositionTypes[i].string;
107  }
108  }
109  return nullptr;
110 }
111 
112 //
113 // disposition-modifier
114 //
115 static const struct {
116  DispositionModifier dispositionModifier;
117  const char *string;
118 } dispositionModifiers[] = {
119  { Error, "error" },
120  { Warning, "warning" },
121  { Superseded, "superseded" },
122  { Expired, "expired" },
123  { MailboxTerminated, "mailbox-terminated" }
124 };
125 
126 static const int numDispositionModifiers =
127  sizeof dispositionModifiers / sizeof *dispositionModifiers;
128 
129 static const char *stringFor(DispositionModifier m)
130 {
131  for (int i = 0 ; i < numDispositionModifiers ; ++i) {
132  if (dispositionModifiers[i].dispositionModifier == m) {
133  return dispositionModifiers[i].string;
134  }
135  }
136  return nullptr;
137 }
138 
139 //
140 // action-mode (part of disposition-mode)
141 //
142 
143 static const struct {
144  ActionMode actionMode;
145  const char *string;
146 } actionModes[] = {
147  { ManualAction, "manual-action" },
148  { AutomaticAction, "automatic-action" }
149 };
150 
151 static const int numActionModes =
152  sizeof actionModes / sizeof *actionModes;
153 
154 static const char *stringFor(ActionMode a)
155 {
156  for (int i = 0 ; i < numActionModes ; ++i) {
157  if (actionModes[i].actionMode == a) {
158  return actionModes[i].string;
159  }
160  }
161  return nullptr;
162 }
163 
164 //
165 // sending-mode (part of disposition-mode)
166 //
167 
168 static const struct {
169  SendingMode sendingMode;
170  const char *string;
171 } sendingModes[] = {
172  { SentManually, "MDN-sent-manually" },
173  { SentAutomatically, "MDN-sent-automatically" }
174 };
175 
176 static const int numSendingModes =
177  sizeof sendingModes / sizeof *sendingModes;
178 
179 static const char *stringFor(SendingMode s)
180 {
181  for (int i = 0 ; i < numSendingModes ; ++i) {
182  if (sendingModes[i].sendingMode == s) {
183  return sendingModes[i].string;
184  }
185  }
186  return nullptr;
187 }
188 
189 static QByteArray dispositionField(DispositionType d, ActionMode a, SendingMode s,
191 {
192 
193  // mandatory parts: Disposition: foo/baz; bar
194  QByteArray result = "Disposition: ";
195  result += stringFor(a);
196  result += '/';
197  result += stringFor(s);
198  result += "; ";
199  result += stringFor(d);
200 
201  // optional parts: Disposition: foo/baz; bar/mod1,mod2,mod3
202  bool first = true;
204  mt != m.end() ; ++mt) {
205  if (first) {
206  result += '/';
207  first = false;
208  } else {
209  result += ',';
210  }
211  result += stringFor(*mt);
212  }
213  return result + '\n';
214 }
215 
216 static QByteArray finalRecipient(const QString &recipient)
217 {
218  if (recipient.isEmpty()) {
219  return QByteArray();
220  } else {
221  return "Final-Recipient: rfc822; "
222  + encodeRFC2047String(recipient, "utf-8") + '\n';
223  }
224 }
225 
226 static QByteArray orginalRecipient(const QByteArray &recipient)
227 {
228  if (recipient.isEmpty()) {
229  return QByteArray();
230  } else {
231  return "Original-Recipient: " + recipient + '\n';
232  }
233 }
234 
235 static QByteArray originalMessageID(const QByteArray &msgid)
236 {
237  if (msgid.isEmpty()) {
238  return QByteArray();
239  } else {
240  return "Original-Message-ID: " + msgid + '\n';
241  }
242 }
243 
244 static QByteArray reportingUAField()
245 {
246  char hostName[256];
247  if (gethostname(hostName, 255)) {
248  hostName[0] = '\0'; // gethostname failed: pretend empty string
249  } else {
250  hostName[255] = '\0'; // gethostname may have returned 255 chars (man page)
251  }
252  return QByteArray("Reporting-UA: ") + QByteArray(hostName) +
253  QByteArray("; KMime " KMIME_VERSION_STRING "\n");
254 }
255 
257  const QByteArray &o,
258  const QByteArray &omid,
259  DispositionType d,
260  ActionMode a,
261  SendingMode s,
263  const QString &special)
264 {
265  // in Perl: chomp(special)
266  QString spec;
267  if (special.endsWith(QLatin1Char('\n'))) {
268  spec = special.left(special.length() - 1);
269  } else {
270  spec = special;
271  }
272 
273  // std headers:
274  QByteArray result = reportingUAField();
275  result += orginalRecipient(o);
276  result += finalRecipient(r);
277  result += originalMessageID(omid);
278  result += dispositionField(d, a, s, m);
279 
280  // headers that are only present for certain disposition {types,modifiers}:
281  if (d == Failed) {
282  result += "Failure: " + encodeRFC2047String(spec, "utf-8") + '\n';
283  } else if (m.contains(Error)) {
284  result += "Error: " + encodeRFC2047String(spec, "utf-8") + '\n';
285  } else if (m.contains(Warning)) {
286  result += "Warning: " + encodeRFC2047String(spec, "utf-8") + '\n';
287  }
288 
289  return result;
290 }
291 
292 QString descriptionFor(DispositionType d,
294 {
295  for (int i = 0 ; i < numDispositionTypes ; ++i) {
296  if (dispositionTypes[i].dispositionType == d) {
297  return i18n(dispositionTypes[i].description);
298  }
299  }
300  qCWarning(KMIME_LOG) << "KMime::MDN::descriptionFor(): No such disposition type:"
301  << static_cast<int>(d);
302  return QString();
303 }
304 
305 } // namespace MDN
306 } // namespace KMime
ActionMode
The following disposition modes are defined:
Definition: kmime_mdn.h:156
QVector::iterator begin()
AKONADI_MIME_EXPORT const char Deleted[]
bool isEmpty() const const
This file is part of the API for handling MIME data and provides functions for supporting Message Dis...
QByteArray dispositionNotificationBodyContent(const QString &r, const QByteArray &o, const QByteArray &omid, DispositionType d, ActionMode a, SendingMode s, const QVector< DispositionModifier > &m, const QString &special)
Generates the content of the message/disposition-notification body part.
Definition: kmime_mdn.cpp:256
bool contains(const T &value) const const
bool isEmpty() const const
#define I18N_NOOP(text)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString i18n(const char *text, const TYPE &arg...)
DispositionModifier
The following disposition modifiers are defined:
Definition: kmime_mdn.h:133
KIMAP_EXPORT const QString encodeRFC2047String(const QString &str)
int length() const const
QString left(int n) const const
QVector::iterator end()
DispositionType
The following disposition-types are defined:
Definition: kmime_mdn.h:103
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat Jul 11 2020 23:11:42 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.