00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "kmime_mdn.h"
00033
00034 #include "kmime_version.h"
00035 #include "kmime_util.h"
00036
00037 #include <klocale.h>
00038 #include <kdebug.h>
00039
00040 #include <qcstring.h>
00041
00042 #include <unistd.h>
00043
00044 namespace KMime {
00045
00046 namespace MDN {
00047
00048 static const struct {
00049 DispositionType dispositionType;
00050 const char * string;
00051 const char * description;
00052 } dispositionTypes[] = {
00053 { Displayed, "displayed",
00054 I18N_NOOP("The message sent on ${date} to ${to} with subject "
00055 "\"${subject}\" has been displayed. This is no guarantee that "
00056 "the message has been read or understood.") },
00057 { Deleted, "deleted",
00058 I18N_NOOP("The message sent on ${date} to ${to} with subject "
00059 "\"${subject}\" has been deleted unseen. This is no guarantee "
00060 "that the message will not be \"undeleted\" and nonetheless "
00061 "read later on.") },
00062 { Dispatched, "dispatched",
00063 I18N_NOOP("The message sent on ${date} to ${to} with subject "
00064 "\"${subject}\" has been dispatched. This is no guarantee "
00065 "that the message will not be read later on.") },
00066 { Processed, "processed",
00067 I18N_NOOP("The message sent on ${date} to ${to} with subject "
00068 "\"${subject}\" has been processed by some automatic means.") },
00069 { Denied, "denied",
00070 I18N_NOOP("The message sent on ${date} to ${to} with subject "
00071 "\"${subject}\" has been acted upon. The sender does not wish "
00072 "to disclose more details to you than that.") },
00073 { Failed, "failed",
00074 I18N_NOOP("Generation of a Message Disposition Notification for the "
00075 "message sent on ${date} to ${to} with subject \"${subject}\" "
00076 "failed. Reason is given in the Failure: header field below.") }
00077 };
00078
00079 static const int numDispositionTypes
00080 = sizeof dispositionTypes / sizeof *dispositionTypes;
00081
00082
00083 static const char * stringFor( DispositionType d ) {
00084 for ( int i = 0 ; i < numDispositionTypes ; ++i )
00085 if ( dispositionTypes[i].dispositionType == d )
00086 return dispositionTypes[i].string;
00087 return 0;
00088 }
00089
00090
00091
00092
00093
00094 static const struct {
00095 DispositionModifier dispositionModifier;
00096 const char * string;
00097 } dispositionModifiers[] = {
00098 { Error, "error" },
00099 { Warning, "warning" },
00100 { Superseded, "superseded" },
00101 { Expired, "expired" },
00102 { MailboxTerminated, "mailbox-terminated" }
00103 };
00104
00105 static const int numDispositionModifiers
00106 = sizeof dispositionModifiers / sizeof * dispositionModifiers;
00107
00108
00109 static const char * stringFor( DispositionModifier m ) {
00110 for ( int i = 0 ; i < numDispositionModifiers ; ++i )
00111 if ( dispositionModifiers[i].dispositionModifier == m )
00112 return dispositionModifiers[i].string;
00113 return 0;
00114 }
00115
00116
00117
00118
00119
00120 static const struct {
00121 ActionMode actionMode;
00122 const char * string;
00123 } actionModes[] = {
00124 { ManualAction, "manual-action" },
00125 { AutomaticAction, "automatic-action" }
00126 };
00127
00128 static const int numActionModes = sizeof actionModes / sizeof *actionModes;
00129
00130 static const char * stringFor( ActionMode a ) {
00131 for ( int i = 0 ; i < numActionModes ; ++i )
00132 if ( actionModes[i].actionMode == a )
00133 return actionModes[i].string;
00134 return 0;
00135 }
00136
00137
00138
00139
00140
00141
00142 static const struct {
00143 SendingMode sendingMode;
00144 const char * string;
00145 } sendingModes[] = {
00146 { SentManually, "MDN-sent-manually" },
00147 { SentAutomatically, "MDN-sent-automatically" }
00148 };
00149
00150 static const int numSendingModes = sizeof sendingModes / sizeof *sendingModes;
00151
00152 static const char * stringFor( SendingMode s ) {
00153 for ( int i = 0 ; i < numSendingModes ; ++i )
00154 if ( sendingModes[i].sendingMode == s )
00155 return sendingModes[i].string;
00156 return 0;
00157 }
00158
00159 static QCString dispositionField( DispositionType d, ActionMode a, SendingMode s,
00160 const QValueList<DispositionModifier> & m ) {
00161
00162
00163 QCString result = "Disposition: ";
00164 result += stringFor( a );
00165 result += "/";
00166 result += stringFor( s );
00167 result += "; ";
00168 result += stringFor( d );
00169
00170
00171 bool first = true;
00172 for ( QValueList<DispositionModifier>::const_iterator mt = m.begin() ;
00173 mt != m.end() ; ++mt ) {
00174 if ( first ) {
00175 result += "/";
00176 first = false;
00177 } else {
00178 result += ",";
00179 }
00180 result += stringFor( *mt );
00181 }
00182 return result + "\n";
00183 }
00184
00185 static QCString finalRecipient( const QString & recipient ) {
00186 if ( recipient.isEmpty() )
00187 return QCString();
00188 else
00189 return "Final-Recipient: rfc822; "
00190 + encodeRFC2047String( recipient, "utf-8" ) + "\n";
00191 }
00192
00193 static QCString orginalRecipient( const QCString & recipient ) {
00194 if ( recipient.isEmpty() )
00195 return QCString();
00196 else
00197 return "Original-Recipient: " + recipient + "\n";
00198 }
00199
00200 static QCString originalMessageID( const QCString & msgid ) {
00201 if ( msgid.isEmpty() )
00202 return QCString();
00203 else
00204 return "Original-Message-ID: " + msgid + "\n";
00205 }
00206
00207 static QCString reportingUAField() {
00208 char hostName[256];
00209 if ( gethostname( hostName, 255 ) )
00210 hostName[0] = '\0';
00211 else
00212 hostName[255] = '\0';
00213 return QCString("Reporting-UA: ") + hostName
00214 + "; KMime " KMIME_VERSION_STRING "\n";
00215 }
00216
00217 QCString dispositionNotificationBodyContent( const QString & r,
00218 const QCString & o,
00219 const QCString & omid,
00220 DispositionType d,
00221 ActionMode a,
00222 SendingMode s,
00223 const QValueList<DispositionModifier> & m,
00224 const QString & special )
00225 {
00226
00227 QString spec;
00228 if ( special.endsWith("\n") )
00229 spec = special.left( special.length() - 1 );
00230 else
00231 spec = special;
00232
00233
00234 QCString result = reportingUAField();
00235 result += orginalRecipient( o );
00236 result += finalRecipient( r );
00237 result += originalMessageID( omid );
00238 result += dispositionField( d, a, s, m );
00239
00240
00241 if ( d == Failed )
00242 result += "Failure: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00243 else if ( m.contains( Error ) )
00244 result += "Error: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00245 else if ( m.contains( Warning ) )
00246 result += "Warning: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00247
00248 return result;
00249 }
00250
00251 QString descriptionFor( DispositionType d,
00252 const QValueList<DispositionModifier> & ) {
00253 for ( int i = 0 ; i < numDispositionTypes ; ++i )
00254 if ( dispositionTypes[i].dispositionType == d )
00255 return i18n( dispositionTypes[i].description );
00256 kdWarning() << "KMime::MDN::descriptionFor(): No such disposition type: "
00257 << (int)d << endl;
00258 return QString::null;
00259 }
00260
00261 }
00262 }