Messagelib

aliasesexpandjob.cpp
1 /*
2  * This file is part of KMail.
3  *
4  * SPDX-FileCopyrightText: 2010 KDAB
5  * SPDX-FileContributor: Tobias Koenig <[email protected]>
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include "aliasesexpandjob.h"
11 
12 #include "distributionlistexpandjob.h"
13 
14 #include <Akonadi/ContactGroupExpandJob>
15 #include <Akonadi/ContactSearchJob>
16 #include <KEmailAddress>
17 
18 #include <MessageCore/StringUtil>
19 
20 using namespace MessageComposer;
21 
22 AliasesExpandJob::AliasesExpandJob(const QString &recipients, const QString &defaultDomain, QObject *parent)
23  : KJob(parent)
24  , mRecipients(KEmailAddress::splitAddressList(recipients))
25  , mDefaultDomain(defaultDomain)
26 {
27 }
28 
30 
32 {
33  // At first we try to expand the recipient to a distribution list
34  // or nick name and save the results in a map for later lookup
35  for (const QString &recipient : std::as_const(mRecipients)) {
36  // speedup: assume aliases and list names don't contain '@'
37  if (recipient.isEmpty() || recipient.contains(QLatin1Char('@'))) {
38  continue;
39  }
40 
41  // check for distribution list
42  auto expandJob = new DistributionListExpandJob(recipient, this);
43  expandJob->setProperty("recipient", recipient);
44  connect(expandJob, &Akonadi::ContactGroupExpandJob::result, this, &AliasesExpandJob::slotDistributionListExpansionDone);
45  mDistributionListExpansionJobs++;
46  expandJob->start();
47 
48  // check for nick name
49  auto searchJob = new Akonadi::ContactSearchJob(this);
50  searchJob->setProperty("recipient", recipient);
51  searchJob->setQuery(Akonadi::ContactSearchJob::NickName, recipient.toLower());
52  connect(searchJob, &Akonadi::ContactSearchJob::result, this, &AliasesExpandJob::slotNicknameExpansionDone);
53  mNicknameExpansionJobs++;
54  searchJob->start();
55  }
56 
57  if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) {
58  emitResult();
59  }
60 }
61 
63 {
64  return mEmailAddresses;
65 }
66 
68 {
69  return mEmptyDistributionLists;
70 }
71 
72 void AliasesExpandJob::slotDistributionListExpansionDone(KJob *job)
73 {
74  if (job->error()) {
75  setError(job->error());
76  setErrorText(job->errorText());
77  emitResult();
78  return;
79  }
80 
81  const DistributionListExpandJob *expandJob = qobject_cast<DistributionListExpandJob *>(job);
82  const QString recipient = expandJob->property("recipient").toString();
83 
84  DistributionListExpansionResult result;
85  result.addresses = expandJob->addresses();
86  result.isEmpty = expandJob->isEmpty();
87 
88  mDistListExpansionResults.insert(recipient, result);
89 
90  mDistributionListExpansionJobs--;
91  if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) {
92  finishExpansion();
93  }
94 }
95 
96 void AliasesExpandJob::slotNicknameExpansionDone(KJob *job)
97 {
98  if (job->error()) {
99  setError(job->error());
100  setErrorText(job->errorText());
101  emitResult();
102  return;
103  }
104 
105  const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
106  const KContacts::Addressee::List contacts = searchJob->contacts();
107  const QString recipient = searchJob->property("recipient").toString();
108 
109  for (const KContacts::Addressee &contact : contacts) {
110  if (contact.nickName().toLower() == recipient.toLower()) {
111  mNicknameExpansionResults.insert(recipient, contact.fullEmail());
112  break;
113  }
114  }
115 
116  mNicknameExpansionJobs--;
117  if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) {
118  finishExpansion();
119  }
120 }
121 
122 void AliasesExpandJob::finishExpansion()
123 {
124  for (const QString &recipient : std::as_const(mRecipients)) {
125  if (recipient.isEmpty()) {
126  continue;
127  }
128  if (!mEmailAddresses.isEmpty()) {
129  mEmailAddresses += QLatin1String(", ");
130  }
131 
132  const QString receiver = recipient.trimmed();
133 
134  // take prefetched expand distribution list results
135  const DistributionListExpansionResult result = mDistListExpansionResults.value(recipient);
137  QString addrSpec;
138  QString comment;
139 
140  if (result.isEmpty) {
141  KEmailAddress::splitAddress(receiver, displayName, addrSpec, comment);
142  mEmailAddressOnly.append(addrSpec);
143  mEmailAddresses += receiver;
144  mEmptyDistributionLists << receiver;
145  continue;
146  }
147 
148  if (!result.addresses.isEmpty()) {
149  KEmailAddress::splitAddress(result.addresses, displayName, addrSpec, comment);
150  mEmailAddressOnly.append(addrSpec);
151 
152  mEmailAddresses += result.addresses;
153  continue;
154  }
155 
156  // take prefetched expand nick name results
157  const QString recipientValue = mNicknameExpansionResults.value(recipient);
158  if (!recipientValue.isEmpty()) {
159  mEmailAddresses += recipientValue;
160  KEmailAddress::splitAddress(recipientValue, displayName, addrSpec, comment);
161  mEmailAddressOnly.append(addrSpec);
162 
163  continue;
164  }
165 
166  // check whether the address is missing the domain part
167  KEmailAddress::splitAddress(receiver, displayName, addrSpec, comment);
168  if (!addrSpec.contains(QLatin1Char('@'))) {
169  if (!mDefaultDomain.isEmpty()) {
170  mEmailAddresses += KEmailAddress::normalizedAddress(displayName, addrSpec + QLatin1Char('@') + mDefaultDomain, comment);
171  } else {
172  mEmailAddresses += MessageCore::StringUtil::guessEmailAddressFromLoginName(addrSpec);
173  }
174  } else {
175  mEmailAddresses += receiver;
176  }
177  mEmailAddressOnly.append(addrSpec);
178  }
179 
180  emitResult();
181 }
182 
183 QStringList AliasesExpandJob::emailAddressOnly() const
184 {
185  return mEmailAddressOnly;
186 }
187 
188 #include "moc_aliasesexpandjob.cpp"
void append(const T &value)
QString addresses() const
Returns the email addresses of the list members.
Simple interface that both EncryptJob and SignEncryptJob implement so the composer can extract some e...
void setErrorText(const QString &errorText)
void result(KJob *job)
const T value(const Key &key, const T &defaultValue) const const
AliasesExpandJob(const QString &recipients, const QString &defaultDomain, QObject *parent=nullptr)
Creates a new aliases expand job.
QString trimmed() const const
~AliasesExpandJob() override
Destroys the aliases expand job.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KCODECS_EXPORT QStringList splitAddressList(const QString &aStr)
QMap::iterator insert(const Key &key, const T &value)
KCODECS_EXPORT EmailParseResult splitAddress(const QByteArray &address, QByteArray &displayName, QByteArray &addrSpec, QByteArray &comment)
KCODECS_EXPORT QString normalizedAddress(const QString &displayName, const QString &addrSpec, const QString &comment=QString())
void start() override
Starts the job.
bool isEmpty() const const
QString errorText() const
A job to expand a distribution list to its member email addresses.
QString guessEmailAddressFromLoginName(const QString &loginName)
Uses the hostname as domain part and tries to determine the real name from the entries in the passwor...
Definition: stringutil.cpp:509
KContacts::Addressee::List contacts() const
AKONADI_CALENDAR_EXPORT QString displayName(Akonadi::ETMCalendar *calendar, const Akonadi::Collection &collection)
QString toLower() const const
QString addresses() const
Returns the expanded email addresses.
AddresseeList List
bool isEmpty() const
Returns whether the list of email addresses is empty.
void emitResult()
int error() const
QStringList emptyDistributionLists() const
Returns the list of distribution lists that resolved to an empty member list.
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
void setError(int errorCode)
QString toString() const const
QVariant property(const char *name) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Sep 26 2023 04:00:44 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.