callback.cpp
00001 /* -*- c++ -*- 00002 callback.cpp 00003 00004 This file is used by KMail's plugin interface. 00005 Copyright (c) 2004 Bo Thorsen <bo@sonofthor.dk> 00006 00007 KMail is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 KMail is distributed in the hope that it will be useful, but 00013 WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 00021 In addition, as a special exception, the copyright holders give 00022 permission to link the code of this program with any edition of 00023 the TQt library by Trolltech AS, Norway (or with modified versions 00024 of TQt that use the same license as TQt), and distribute linked 00025 combinations including the two. You must obey the GNU General 00026 Public License in all respects for all of the code used other than 00027 TQt. If you modify this file, you may extend this exception to 00028 your version of the file, but you are not obligated to do so. If 00029 you do not wish to do so, delete this exception statement from 00030 your version. 00031 */ 00032 00033 #include "callback.h" 00034 #include "kmkernel.h" 00035 #include "kmmessage.h" 00036 #include "kmmsgpart.h" 00037 #include <libemailfunctions/email.h> 00038 #include <libkpimidentities/identity.h> 00039 #include <libkpimidentities/identitymanager.h> 00040 #include "kmmainwin.h" 00041 #include "composer.h" 00042 #include "kmreaderwin.h" 00043 #include "secondarywindow.h" 00044 #include "transportmanager.h" 00045 00046 #include <mimelib/enum.h> 00047 00048 #include <kinputdialog.h> 00049 #include <klocale.h> 00050 #include <kdebug.h> 00051 00052 using namespace KMail; 00053 00054 00055 Callback::Callback( KMMessage* msg, KMReaderWin* readerWin ) 00056 : mMsg( msg ), mReaderWin( readerWin ), mReceiverSet( false ) 00057 { 00058 } 00059 00060 TQString Callback::askForTransport( bool nullIdentity ) const 00061 { 00062 const TQStringList transports = KMail::TransportManager::transportNames(); 00063 if ( transports.size() == 1 ) 00064 return transports.first(); 00065 00066 const TQString defaultTransport = GlobalSettings::self()->defaultTransport(); 00067 const int defaultIndex = TQMAX( 0, transports.findIndex( defaultTransport ) ); 00068 00069 TQString text; 00070 if ( nullIdentity ) 00071 text = i18n( "<qt>The receiver of this invitation doesn't match any of your identities.<br>" 00072 "Please select the transport which should be used to send your reply.</qt>" ); 00073 else 00074 text = i18n( "<qt>The identity matching the receiver of this invitation doesn't have an " 00075 "associated transport configured.<br>" 00076 "Please select the transport which should be used to send your reply.</qt>"); 00077 bool ok; 00078 const TQString transport = KInputDialog::getItem( i18n( "Select Transport" ), text, 00079 transports, defaultIndex, FALSE, &ok, kmkernel->mainWin() ); 00080 if ( !ok ) 00081 return TQString(); 00082 00083 return transport; 00084 } 00085 00086 bool Callback::mailICal( const TQString& to, const TQString &iCal, 00087 const TQString& subject, const TQString &status, 00088 bool delMessage ) const 00089 { 00090 kdDebug(5006) << "Mailing message:\n" << iCal << endl; 00091 00092 KMMessage *msg = new KMMessage; 00093 msg->initHeader(); 00094 msg->setSubject( subject ); 00095 if ( GlobalSettings::self()->exchangeCompatibleInvitations() ) { 00096 if ( status == TQString("cancel") ) 00097 msg->setSubject( i18n( "Declined: %1" ).arg(subject).replace("Answer: ","") ); 00098 else if ( status == TQString("tentative") ) 00099 msg->setSubject( i18n( "Tentative: %1" ).arg(subject).replace("Answer: ","") ); 00100 else if ( status == TQString("accepted") ) 00101 msg->setSubject( i18n( "Accepted: %1" ).arg(subject).replace("Answer: ","") ); 00102 else if ( status == TQString("delegated") ) 00103 msg->setSubject( i18n( "Delegated: %1" ).arg(subject).replace("Answer: ","") ); 00104 } 00105 msg->setTo( to ); 00106 msg->setFrom( receiver() ); 00107 00108 if ( !GlobalSettings::self()->exchangeCompatibleInvitations() ) { 00109 msg->setHeaderField( "Content-Type", 00110 "text/calendar; method=reply; charset=\"utf-8\"" ); 00111 msg->setBody( iCal.utf8() ); 00112 } 00113 00114 if ( delMessage && deleteInvitationAfterReply() ) 00115 /* We want the triggering mail to be moved to the trash once this one 00116 * has been sent successfully. Set a link header which accomplishes that. */ 00117 msg->link( mMsg, KMMsgStatusDeleted ); 00118 00119 // Try and match the receiver with an identity. 00120 // Setting the identity here is important, as that is used to select the correct 00121 // transport later 00122 const KPIM::Identity& identity = kmkernel->identityManager()->identityForAddress( receiver() ); 00123 const bool nullIdentity = ( identity == KPIM::Identity::null() ); 00124 if ( !nullIdentity ) { 00125 msg->setHeaderField("X-KMail-Identity", TQString::number( identity.uoid() )); 00126 } 00127 00128 const bool identityHasTransport = !identity.transport().isEmpty(); 00129 if ( !nullIdentity && identityHasTransport ) 00130 msg->setHeaderField( "X-KMail-Transport", identity.transport() ); 00131 else if ( !nullIdentity && identity.isDefault() ) 00132 msg->setHeaderField( "X-KMail-Transport", GlobalSettings::self()->defaultTransport() ); 00133 else { 00134 const TQString transport = askForTransport( nullIdentity ); 00135 if ( transport.isEmpty() ) 00136 return false; // user canceled transport selection dialog 00137 msg->setHeaderField( "X-KMail-Transport", transport ); 00138 } 00139 00140 // Outlook will only understand the reply if the From: header is the 00141 // same as the To: header of the invitation message. 00142 KConfigGroup options( KMKernel::config(), "Groupware" ); 00143 if( !options.readBoolEntry( "LegacyMangleFromToHeaders", true ) ) { 00144 if( identity != KPIM::Identity::null() ) { 00145 msg->setFrom( identity.fullEmailAddr() ); 00146 } 00147 // Remove BCC from identity on ical invitations (https://intevation.de/roundup/kolab/issue474) 00148 msg->setBcc( "" ); 00149 } 00150 00151 KMail::Composer * cWin = KMail::makeComposer(); 00152 cWin->ignoreStickyFields(); 00153 cWin->setMsg( msg, false /* mayAutoSign */ ); 00154 // cWin->setCharset( "", true ); 00155 cWin->disableWordWrap(); 00156 cWin->setSigningAndEncryptionDisabled( true ); 00157 00158 if( GlobalSettings::self()->exchangeCompatibleInvitations() ) { 00159 // For Exchange, send ical as attachment, with proper 00160 // parameters 00161 msg->setSubject( status ); 00162 msg->setCharset( "utf-8" ); 00163 KMMessagePart *msgPart = new KMMessagePart; 00164 msgPart->setName( "cal.ics" ); 00165 // msgPart->setCteStr( attachCte ); // "base64" ? 00166 msgPart->setBodyEncoded( iCal.utf8() ); 00167 msgPart->setTypeStr( "text" ); 00168 msgPart->setSubtypeStr( "calendar" ); 00169 msgPart->setParameter( "method", "reply" ); 00170 cWin->addAttach( msgPart ); 00171 } 00172 00173 cWin->disableRecipientNumberCheck(); 00174 cWin->disableForgottenAttachmentsCheck(); 00175 if ( options.readBoolEntry( "AutomaticSending", true ) ) { 00176 cWin->setAutoDeleteWindow( true ); 00177 cWin->slotSendNow(); 00178 } else { 00179 cWin->show(); 00180 } 00181 00182 return true; 00183 } 00184 00185 TQString Callback::receiver() const 00186 { 00187 if ( mReceiverSet ) 00188 // Already figured this out 00189 return mReceiver; 00190 00191 mReceiverSet = true; 00192 00193 TQStringList addrs = KPIM::splitEmailAddrList( mMsg->to() ); 00194 int found = 0; 00195 for( TQStringList::Iterator it = addrs.begin(); it != addrs.end(); ++it ) { 00196 if( kmkernel->identityManager()->identityForAddress( *it ) != 00197 KPIM::Identity::null() ) { 00198 // Ok, this could be us 00199 ++found; 00200 mReceiver = *it; 00201 } 00202 } 00203 TQStringList ccaddrs = KPIM::splitEmailAddrList( mMsg->cc() ); 00204 for( TQStringList::Iterator it = ccaddrs.begin(); it != ccaddrs.end(); ++it ) { 00205 if( kmkernel->identityManager()->identityForAddress( *it ) != 00206 KPIM::Identity::null() ) { 00207 // Ok, this could be us 00208 ++found; 00209 mReceiver = *it; 00210 } 00211 } 00212 if( found != 1 ) { 00213 bool ok; 00214 TQString selectMessage; 00215 if (found == 0) { 00216 selectMessage = i18n("<qt>None of your identities match the " 00217 "receiver of this message,<br>please " 00218 "choose which of the following addresses " 00219 "is yours, if any, or select one of your identities to use in the reply:"); 00220 addrs += kmkernel->identityManager()->allEmails(); 00221 } else { 00222 selectMessage = i18n("<qt>Several of your identities match the " 00223 "receiver of this message,<br>please " 00224 "choose which of the following addresses " 00225 "is yours:"); 00226 } 00227 00228 // select default identity by default 00229 const TQString defaultAddr = kmkernel->identityManager()->defaultIdentity().primaryEmailAddress(); 00230 const int defaultIndex = TQMAX( 0, addrs.findIndex( defaultAddr ) ); 00231 00232 mReceiver = 00233 KInputDialog::getItem( i18n( "Select Address" ), 00234 selectMessage, 00235 addrs+ccaddrs, defaultIndex, FALSE, &ok, kmkernel->mainWin() ); 00236 if( !ok ) 00237 mReceiver = TQString(); 00238 } 00239 00240 return mReceiver; 00241 } 00242 00243 void Callback::closeIfSecondaryWindow() const 00244 { 00245 KMail::SecondaryWindow *window = dynamic_cast<KMail::SecondaryWindow*>( mReaderWin->mainWindow() ); 00246 if ( window ) 00247 window->close(); 00248 } 00249 00250 bool Callback::askForComment( KCal::Attendee::PartStat status ) const 00251 { 00252 if ( ( status != KCal::Attendee::Accepted 00253 && GlobalSettings::self()->askForCommentWhenReactingToInvitation() 00254 == GlobalSettings:: EnumAskForCommentWhenReactingToInvitation::AskForAllButAcceptance ) 00255 || GlobalSettings::self()->askForCommentWhenReactingToInvitation() 00256 == GlobalSettings:: EnumAskForCommentWhenReactingToInvitation::AlwaysAsk ) 00257 return true; 00258 return false; 00259 } 00260 00261 bool Callback::deleteInvitationAfterReply() const 00262 { 00263 return GlobalSettings::self()->deleteInvitationEmailsAfterSendingReply(); 00264 } 00265 00266 bool Callback::exchangeCompatibleInvitations() const 00267 { 00268 return GlobalSettings::self()->exchangeCompatibleInvitations(); 00269 } 00270 00271 bool Callback::outlookCompatibleInvitationReplyComments() const 00272 { 00273 return GlobalSettings::self()->outlookCompatibleInvitationReplyComments(); 00274 } 00275 00276 TQString Callback::sender() const 00277 { 00278 return mMsg->from(); 00279 }