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

korgac

  • sources
  • kde-4.12
  • kdepim
  • korgac
mailclient.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1998 Barry D Benowitz <b.benowitz@telesciences.com>
3  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4  Copyright (c) 2009 Allen Winter <winter@kde.org>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of Qt, and distribute the resulting executable,
22  without including the source code for Qt in the source distribution.
23 */
24 
25 #include <config-enterprise.h>
26 
27 #include "mailclient.h"
28 #include "kdepim-version.h"
29 
30 #include <Akonadi/Collection>
31 
32 #include <KCalCore/Attendee>
33 #include <KCalCore/Incidence>
34 #include <KCalCore/IncidenceBase>
35 
36 #include <KCalUtils/IncidenceFormatter>
37 
38 #include <KMime/Message>
39 
40 #include <KPIMIdentities/Identity>
41 
42 #include <KPIMUtils/Email>
43 
44 #include <Mailtransport/MessageQueueJob>
45 #include <Mailtransport/Transport>
46 #include <Mailtransport/TransportManager>
47 
48 #include <KDebug>
49 #include <KLocale>
50 #include <KProtocolManager>
51 #include <KSystemTimeZone>
52 
53 using namespace KOrg;
54 
55 MailClient::MailClient() : QObject()
56 {
57 }
58 
59 MailClient::~MailClient()
60 {
61 }
62 
63 bool MailClient::mailAttendees( const KCalCore::IncidenceBase::Ptr &incidence,
64  const KPIMIdentities::Identity &identity,
65  bool bccMe, const QString &attachment,
66  const QString &mailTransport )
67 {
68  KCalCore::Attendee::List attendees = incidence->attendees();
69  if ( attendees.isEmpty() ) {
70  kWarning() << "There are no attendees to e-mail";
71  return false;
72  }
73 
74  const QString from = incidence->organizer()->fullName();
75  const QString organizerEmail = incidence->organizer()->email();
76 
77  QStringList toList;
78  QStringList ccList;
79  const int numberOfAttendees( attendees.count() );
80  for ( int i=0; i<numberOfAttendees; ++i ) {
81  KCalCore::Attendee::Ptr a = attendees.at(i);
82 
83  const QString email = a->email();
84  if ( email.isEmpty() ) {
85  continue;
86  }
87 
88  // In case we (as one of our identities) are the organizer we are sending
89  // this mail. We could also have added ourselves as an attendee, in which
90  // case we don't want to send ourselves a notification mail.
91  if ( organizerEmail == email ) {
92  continue;
93  }
94 
95  // Build a nice address for this attendee including the CN.
96  QString tname, temail;
97  const QString username = KPIMUtils::quoteNameIfNecessary( a->name() );
98  // ignore the return value from extractEmailAddressAndName() because
99  // it will always be false since tusername does not contain "@domain".
100  KPIMUtils::extractEmailAddressAndName( username, temail/*byref*/, tname/*byref*/ );
101  tname += QLatin1String( " <" ) + email + QLatin1Char( '>' );
102 
103  // Optional Participants and Non-Participants are copied on the email
104  if ( a->role() == KCalCore::Attendee::OptParticipant ||
105  a->role() == KCalCore::Attendee::NonParticipant ) {
106  ccList << tname;
107  } else {
108  toList << tname;
109  }
110  }
111  if( toList.isEmpty() && ccList.isEmpty() ) {
112  // Not really to be called a groupware meeting, eh
113  kWarning() << "There are really no attendees to e-mail";
114  return false;
115  }
116  QString to;
117  if ( !toList.isEmpty() ) {
118  to = toList.join( QLatin1String( ", " ) );
119  }
120  QString cc;
121  if ( !ccList.isEmpty() ) {
122  cc = ccList.join( QLatin1String( ", " ) );
123  }
124 
125  QString subject;
126  if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) {
127  KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>();
128  subject = inc->summary();
129  } else {
130  subject = i18n( "Free Busy Object" );
131  }
132 
133  const QString body =
134  KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
135 
136  return send( identity, from, to, cc, subject, body, false,
137  bccMe, attachment, mailTransport );
138 }
139 
140 bool MailClient::mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence,
141  const KPIMIdentities::Identity &identity,
142  const QString &from, bool bccMe,
143  const QString &attachment,
144  const QString &sub, const QString &mailTransport )
145 {
146  const QString to = incidence->organizer()->fullName();
147  QString subject = sub;
148 
149  if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) {
150  KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>();
151  if ( subject.isEmpty() ) {
152  subject = inc->summary();
153  }
154  } else {
155  subject = i18n( "Free Busy Message" );
156  }
157 
158  QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
159 
160  return send( identity, from, to, QString(), subject, body, false,
161  bccMe, attachment, mailTransport );
162 }
163 
164 bool MailClient::mailTo( const KCalCore::IncidenceBase::Ptr &incidence,
165  const KPIMIdentities::Identity &identity,
166  const QString &from, bool bccMe,
167  const QString &recipients, const QString &attachment,
168  const QString &mailTransport )
169 {
170  QString subject;
171 
172  if ( incidence->type() != KCalCore::Incidence::TypeFreeBusy ) {
173  KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>() ;
174  subject = inc->summary();
175  } else {
176  subject = i18n( "Free Busy Message" );
177  }
178  const QString body =
179  KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
180 
181  return send( identity, from, recipients, QString(), subject, body, false,
182  bccMe, attachment, mailTransport );
183 }
184 
185 QStringList extractEmailAndNormalize( const QString& email )
186 {
187  const QStringList splittedEmail = KPIMUtils::splitAddressList( email );
188  QStringList normalizedEmail;
189  Q_FOREACH( const QString& email, splittedEmail )
190  {
191  const QString str = KPIMUtils::extractEmailAddress( KPIMUtils::normalizeAddressesAndEncodeIdn( email ) );
192  normalizedEmail << str;
193  }
194  return normalizedEmail;
195 }
196 
197 bool MailClient::send( const KPIMIdentities::Identity &identity,
198  const QString &from, const QString &_to,
199  const QString &cc, const QString &subject,
200  const QString &body, bool hidden, bool bccMe,
201  const QString &attachment, const QString &mailTransport )
202 {
203  Q_UNUSED( hidden );
204 
205  if ( !MailTransport::TransportManager::self()->showTransportCreationDialog(
206  0, MailTransport::TransportManager::IfNoTransportExists ) ) {
207  return false;
208  }
209 
210  // We must have a recipients list for most MUAs. Thus, if the 'to' list
211  // is empty simply use the 'from' address as the recipient.
212  QString to = _to;
213  if ( to.isEmpty() ) {
214  to = from;
215  }
216  kDebug() << "\nFrom:" << from
217  << "\nTo:" << to
218  << "\nCC:" << cc
219  << "\nSubject:" << subject << "\nBody: \n" << body
220  << "\nAttachment:\n" << attachment
221  << "\nmailTransport: " << mailTransport;
222 
223  QTime timer;
224  timer.start();
225 
226  MailTransport::Transport *transport =
227  MailTransport::TransportManager::self()->transportByName( mailTransport );
228 
229  if ( !transport ) {
230  transport =
231  MailTransport::TransportManager::self()->transportByName(
232  MailTransport::TransportManager::self()->defaultTransportName() );
233  }
234 
235  if ( !transport ) {
236  // TODO: we need better error handling. Currently korganizer says "Error sending invitation".
237  // Using a boolean for errors isn't granular enough.
238  kError() << "Error fetching transport; mailTransport"
239  << mailTransport << MailTransport::TransportManager::self()->defaultTransportName();
240  return false;
241  }
242 
243  const int transportId = transport->id();
244 
245  // gather config values
246  KConfig config( QLatin1String("kmail2rc") );
247 
248  KConfigGroup configGroup( &config, QLatin1String( "Invitations" ) );
249  const bool outlookConformInvitation = configGroup.readEntry( "LegacyBodyInvites",
250 #ifdef KDEPIM_ENTERPRISE_BUILD
251  true
252 #else
253  false
254 #endif
255  );
256 
257  // Now build the message we like to send. The message KMime::Message::Ptr instance
258  // will be the root message that has 2 additional message. The body itself and
259  // the attached cal.ics calendar file.
260  KMime::Message::Ptr message = KMime::Message::Ptr( new KMime::Message );
261  message->contentTransferEncoding()->clear(); // 7Bit, decoded.
262 
263  // Set the headers
264  message->userAgent()->fromUnicodeString(
265  KProtocolManager::userAgentForApplication(
266  QLatin1String( "KOrganizer" ), QLatin1String( KDEPIM_VERSION ) ), "utf-8" );
267  message->from()->fromUnicodeString( from, "utf-8" );
268  message->to()->fromUnicodeString( to, "utf-8" );
269  message->cc()->fromUnicodeString( cc, "utf-8" );
270  if( bccMe ) {
271  message->bcc()->fromUnicodeString( from, "utf-8" ); //from==me, right?
272  }
273  message->date()->setDateTime( KDateTime::currentLocalDateTime() );
274  message->subject()->fromUnicodeString( subject, "utf-8" );
275 
276  if ( outlookConformInvitation ) {
277  message->contentType()->setMimeType( "text/calendar" );
278  message->contentType()->setCharset( "utf-8" );
279  message->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
280  message->contentType()->setParameter( QLatin1String( "method" ), QLatin1String( "request" ) );
281 
282  if ( !attachment.isEmpty() ) {
283  KMime::Headers::ContentDisposition *disposition =
284  new KMime::Headers::ContentDisposition( message.get() );
285  disposition->setDisposition( KMime::Headers::CDinline );
286  message->setHeader( disposition );
287  message->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
288  message->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
289  }
290  } else {
291  // We need to set following 4 lines by hand else KMime::Content::addContent
292  // will create a new Content instance for us to attach the main message
293  // what we don't need cause we already have the main message instance where
294  // 2 additional messages are attached.
295  KMime::Headers::ContentType *ct = message->contentType();
296  ct->setMimeType( "multipart/mixed" );
297  ct->setBoundary( KMime::multiPartBoundary() );
298  ct->setCategory( KMime::Headers::CCcontainer );
299 
300  // Set the first multipart, the body message.
301  KMime::Content *bodyMessage = new KMime::Content;
302  KMime::Headers::ContentDisposition *bodyDisposition =
303  new KMime::Headers::ContentDisposition( bodyMessage );
304  bodyDisposition->setDisposition( KMime::Headers::CDinline );
305  bodyMessage->contentType()->setMimeType( "text/plain" );
306  bodyMessage->contentType()->setCharset( "utf-8" );
307  bodyMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
308  bodyMessage->setBody( KMime::CRLFtoLF( body.toUtf8() ) );
309  message->addContent( bodyMessage );
310 
311  // Set the sedcond multipart, the attachment.
312  if ( !attachment.isEmpty() ) {
313  KMime::Content *attachMessage = new KMime::Content;
314  KMime::Headers::ContentDisposition *attachDisposition =
315  new KMime::Headers::ContentDisposition( attachMessage );
316  attachDisposition->setDisposition( KMime::Headers::CDattachment );
317  attachMessage->contentType()->setMimeType( "text/calendar" );
318  attachMessage->contentType()->setCharset( "utf-8" );
319  attachMessage->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
320  attachMessage->contentType()->setParameter( QLatin1String( "method" ),
321  QLatin1String( "request" ) );
322  attachMessage->setHeader( attachDisposition );
323  attachMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
324  attachMessage->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
325  message->addContent( attachMessage );
326  }
327  }
328 
329  // Job done, attach the both multiparts and assemble the message.
330  message->assemble();
331 
332  // Put the newly created item in the MessageQueueJob.
333  MailTransport::MessageQueueJob *qjob = new MailTransport::MessageQueueJob( this );
334  qjob->transportAttribute().setTransportId( transportId );
335 
336  if (identity.disabledFcc()) {
337  qjob->sentBehaviourAttribute().setSentBehaviour( MailTransport::SentBehaviourAttribute::Delete );
338  } else {
339  const Akonadi::Collection sentCollection( identity.fcc().toLongLong() );
340  if (sentCollection.isValid()) {
341  qjob->sentBehaviourAttribute().setSentBehaviour( MailTransport::SentBehaviourAttribute::MoveToCollection );
342  qjob->sentBehaviourAttribute().setMoveToCollection( sentCollection );
343  } else {
344  qjob->sentBehaviourAttribute().setSentBehaviour(
345  MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection );
346  }
347  }
348 
349  if ( transport && transport->specifySenderOverwriteAddress() ) {
350  qjob->addressAttribute().setFrom(
351  KPIMUtils::extractEmailAddress(
352  KPIMUtils::normalizeAddressesAndEncodeIdn( transport->senderOverwriteAddress() ) ) );
353  } else {
354  qjob->addressAttribute().setFrom(
355  KPIMUtils::extractEmailAddress(
356  KPIMUtils::normalizeAddressesAndEncodeIdn( from ) ) );
357  }
358 
359  if( !to.isEmpty() ) {
360  qjob->addressAttribute().setTo( extractEmailAndNormalize( to ) );
361  }
362  if( !cc.isEmpty() ) {
363  qjob->addressAttribute().setCc( extractEmailAndNormalize( cc ) );
364  }
365  if ( bccMe ) {
366  qjob->addressAttribute().setBcc( extractEmailAndNormalize( from ) );
367  }
368  qjob->setMessage( message );
369  if ( !qjob->exec() ) {
370  kWarning() << "Error queuing message in outbox:" << qjob->errorText();
371  return false;
372  }
373 
374  // Everything done successful now.
375  kDebug() << "Send mail finished. Time elapsed in ms:" << timer.elapsed();
376  return true;
377 }
KOrg::MailClient::mailOrganizer
bool mailOrganizer(const KCalCore::IncidenceBase::Ptr &, const KPIMIdentities::Identity &identity, const QString &from, bool bccMe, const QString &attachment=QString(), const QString &sub=QString(), const QString &mailTransport=QString())
Definition: mailclient.cpp:140
KOrg::MailClient::send
bool send(const KPIMIdentities::Identity &identity, const QString &from, const QString &to, const QString &cc, const QString &subject, const QString &body, bool hidden=false, bool bccMe=false, const QString &attachment=QString(), const QString &mailTransport=QString())
Sends mail with specified from, to and subject field and body as text.
Definition: mailclient.cpp:197
KOrg::MailClient::mailAttendees
bool mailAttendees(const KCalCore::IncidenceBase::Ptr &, const KPIMIdentities::Identity &identity, bool bccMe, const QString &attachment=QString(), const QString &mailTransport=QString())
Definition: mailclient.cpp:63
QObject
KOrg::MailClient::~MailClient
~MailClient()
Definition: mailclient.cpp:59
mailclient.h
KOrg::MailClient::mailTo
bool mailTo(const KCalCore::IncidenceBase::Ptr &, const KPIMIdentities::Identity &identity, const QString &from, bool bccMe, const QString &recipients, const QString &attachment=QString(), const QString &mailTransport=QString())
Definition: mailclient.cpp:164
extractEmailAndNormalize
QStringList extractEmailAndNormalize(const QString &email)
Definition: mailclient.cpp:185
KOrg::MailClient::MailClient
MailClient()
Definition: mailclient.cpp:55
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:55:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

korgac

Skip menu "korgac"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

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