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

korgac

  • sources
  • kde-4.14
  • 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  const 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 = MailTransport::TransportManager::self()->transportById(MailTransport::TransportManager::self()->defaultTransportId(), false);
231  }
232 
233  if ( !transport ) {
234  // TODO: we need better error handling. Currently korganizer says "Error sending invitation".
235  // Using a boolean for errors isn't granular enough.
236  kError() << "Error fetching transport; mailTransport"
237  << mailTransport << MailTransport::TransportManager::self()->defaultTransportName();
238  return false;
239  }
240 
241  const int transportId = transport->id();
242 
243  // gather config values
244  KConfig config( QLatin1String("kmail2rc") );
245 
246  KConfigGroup configGroup( &config, QLatin1String( "Invitations" ) );
247  const bool outlookConformInvitation = configGroup.readEntry( "LegacyBodyInvites",
248 #ifdef KDEPIM_ENTERPRISE_BUILD
249  true
250 #else
251  false
252 #endif
253  );
254 
255  // Now build the message we like to send. The message KMime::Message::Ptr instance
256  // will be the root message that has 2 additional message. The body itself and
257  // the attached cal.ics calendar file.
258  KMime::Message::Ptr message = KMime::Message::Ptr( new KMime::Message );
259  message->contentTransferEncoding()->clear(); // 7Bit, decoded.
260 
261  // Set the headers
262  message->userAgent()->fromUnicodeString(
263  KProtocolManager::userAgentForApplication(
264  QLatin1String( "KOrganizer" ), QLatin1String( KDEPIM_VERSION ) ), "utf-8" );
265  message->from()->fromUnicodeString( from, "utf-8" );
266  message->to()->fromUnicodeString( to, "utf-8" );
267  message->cc()->fromUnicodeString( cc, "utf-8" );
268  if( bccMe ) {
269  message->bcc()->fromUnicodeString( from, "utf-8" ); //from==me, right?
270  }
271  message->date()->setDateTime( KDateTime::currentLocalDateTime() );
272  message->subject()->fromUnicodeString( subject, "utf-8" );
273 
274  if ( outlookConformInvitation ) {
275  message->contentType()->setMimeType( "text/calendar" );
276  message->contentType()->setCharset( "utf-8" );
277  message->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
278  message->contentType()->setParameter( QLatin1String( "method" ), QLatin1String( "request" ) );
279 
280  if ( !attachment.isEmpty() ) {
281  KMime::Headers::ContentDisposition *disposition =
282  new KMime::Headers::ContentDisposition( message.get() );
283  disposition->setDisposition( KMime::Headers::CDinline );
284  message->setHeader( disposition );
285  message->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
286  message->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
287  }
288  } else {
289  // We need to set following 4 lines by hand else KMime::Content::addContent
290  // will create a new Content instance for us to attach the main message
291  // what we don't need cause we already have the main message instance where
292  // 2 additional messages are attached.
293  KMime::Headers::ContentType *ct = message->contentType();
294  ct->setMimeType( "multipart/mixed" );
295  ct->setBoundary( KMime::multiPartBoundary() );
296  ct->setCategory( KMime::Headers::CCcontainer );
297 
298  // Set the first multipart, the body message.
299  KMime::Content *bodyMessage = new KMime::Content;
300  KMime::Headers::ContentDisposition *bodyDisposition =
301  new KMime::Headers::ContentDisposition( bodyMessage );
302  bodyDisposition->setDisposition( KMime::Headers::CDinline );
303  bodyMessage->contentType()->setMimeType( "text/plain" );
304  bodyMessage->contentType()->setCharset( "utf-8" );
305  bodyMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
306  bodyMessage->setBody( KMime::CRLFtoLF( body.toUtf8() ) );
307  message->addContent( bodyMessage );
308 
309  // Set the sedcond multipart, the attachment.
310  if ( !attachment.isEmpty() ) {
311  KMime::Content *attachMessage = new KMime::Content;
312  KMime::Headers::ContentDisposition *attachDisposition =
313  new KMime::Headers::ContentDisposition( attachMessage );
314  attachDisposition->setDisposition( KMime::Headers::CDattachment );
315  attachMessage->contentType()->setMimeType( "text/calendar" );
316  attachMessage->contentType()->setCharset( "utf-8" );
317  attachMessage->contentType()->setName( QLatin1String( "cal.ics" ), "utf-8" );
318  attachMessage->contentType()->setParameter( QLatin1String( "method" ),
319  QLatin1String( "request" ) );
320  attachMessage->setHeader( attachDisposition );
321  attachMessage->contentTransferEncoding()->setEncoding( KMime::Headers::CEquPr );
322  attachMessage->setBody( KMime::CRLFtoLF( attachment.toUtf8() ) );
323  message->addContent( attachMessage );
324  }
325  }
326 
327  // Job done, attach the both multiparts and assemble the message.
328  message->assemble();
329 
330  // Put the newly created item in the MessageQueueJob.
331  MailTransport::MessageQueueJob *qjob = new MailTransport::MessageQueueJob( this );
332  qjob->transportAttribute().setTransportId( transportId );
333 
334  if (identity.disabledFcc()) {
335  qjob->sentBehaviourAttribute().setSentBehaviour( MailTransport::SentBehaviourAttribute::Delete );
336  } else {
337  const Akonadi::Collection sentCollection( identity.fcc().toLongLong() );
338  if (sentCollection.isValid()) {
339  qjob->sentBehaviourAttribute().setSentBehaviour( MailTransport::SentBehaviourAttribute::MoveToCollection );
340  qjob->sentBehaviourAttribute().setMoveToCollection( sentCollection );
341  } else {
342  qjob->sentBehaviourAttribute().setSentBehaviour(
343  MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection );
344  }
345  }
346 
347  if ( transport && transport->specifySenderOverwriteAddress() ) {
348  qjob->addressAttribute().setFrom(
349  KPIMUtils::extractEmailAddress(
350  KPIMUtils::normalizeAddressesAndEncodeIdn( transport->senderOverwriteAddress() ) ) );
351  } else {
352  qjob->addressAttribute().setFrom(
353  KPIMUtils::extractEmailAddress(
354  KPIMUtils::normalizeAddressesAndEncodeIdn( from ) ) );
355  }
356 
357  if( !to.isEmpty() ) {
358  qjob->addressAttribute().setTo( extractEmailAndNormalize( to ) );
359  }
360  if( !cc.isEmpty() ) {
361  qjob->addressAttribute().setCc( extractEmailAndNormalize( cc ) );
362  }
363  if ( bccMe ) {
364  qjob->addressAttribute().setBcc( extractEmailAndNormalize( from ) );
365  }
366  qjob->setMessage( message );
367  if ( !qjob->exec() ) {
368  kWarning() << "Error queuing message in outbox:" << qjob->errorText();
369  return false;
370  }
371 
372  // Everything done successful now.
373  kDebug() << "Send mail finished. Time elapsed in ms:" << timer.elapsed();
374  return true;
375 }
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
QList::at
const T & at(int i) const
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
QStringList::join
QString join(const QString &separator) const
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
QTime
QTime::elapsed
int elapsed() const
KOrg::MailClient::~MailClient
~MailClient()
Definition: mailclient.cpp:59
mailclient.h
QObject
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
QString
QStringList
QLatin1Char
QLatin1String
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
QTime::start
void start()
KOrg::MailClient::MailClient
MailClient()
Definition: mailclient.cpp:55
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:32:25 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
  • 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