File indexing completed on 2024-06-23 05:18:31
0001 /* 0002 * This file is part of KMail. 0003 * 0004 * SPDX-FileCopyrightText: 2010 KDAB 0005 * SPDX-FileContributor: Tobias Koenig <tokoe@kde.org> 0006 * 0007 * SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "aliasesexpandjob.h" 0011 0012 #include "distributionlistexpandjob.h" 0013 0014 #include <Akonadi/ContactGroupExpandJob> 0015 #include <Akonadi/ContactSearchJob> 0016 #include <KEmailAddress> 0017 0018 #include <MessageCore/StringUtil> 0019 0020 using namespace MessageComposer; 0021 0022 AliasesExpandJob::AliasesExpandJob(const QString &recipients, const QString &defaultDomain, QObject *parent) 0023 : KJob(parent) 0024 , mRecipients(KEmailAddress::splitAddressList(recipients)) 0025 , mDefaultDomain(defaultDomain) 0026 { 0027 } 0028 0029 AliasesExpandJob::~AliasesExpandJob() = default; 0030 0031 void AliasesExpandJob::start() 0032 { 0033 // At first we try to expand the recipient to a distribution list 0034 // or nick name and save the results in a map for later lookup 0035 for (const QString &recipient : std::as_const(mRecipients)) { 0036 // speedup: assume aliases and list names don't contain '@' 0037 if (recipient.isEmpty() || recipient.contains(QLatin1Char('@'))) { 0038 continue; 0039 } 0040 0041 // check for distribution list 0042 auto expandJob = new DistributionListExpandJob(recipient, this); 0043 expandJob->setProperty("recipient", recipient); 0044 connect(expandJob, &Akonadi::ContactGroupExpandJob::result, this, &AliasesExpandJob::slotDistributionListExpansionDone); 0045 mDistributionListExpansionJobs++; 0046 expandJob->start(); 0047 0048 // check for nick name 0049 auto searchJob = new Akonadi::ContactSearchJob(this); 0050 searchJob->setProperty("recipient", recipient); 0051 searchJob->setQuery(Akonadi::ContactSearchJob::NickName, recipient.toLower()); 0052 connect(searchJob, &Akonadi::ContactSearchJob::result, this, &AliasesExpandJob::slotNicknameExpansionDone); 0053 mNicknameExpansionJobs++; 0054 searchJob->start(); 0055 } 0056 0057 if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) { 0058 emitResult(); 0059 } 0060 } 0061 0062 QString AliasesExpandJob::addresses() const 0063 { 0064 return mEmailAddresses; 0065 } 0066 0067 QStringList AliasesExpandJob::emptyDistributionLists() const 0068 { 0069 return mEmptyDistributionLists; 0070 } 0071 0072 void AliasesExpandJob::slotDistributionListExpansionDone(KJob *job) 0073 { 0074 if (job->error()) { 0075 setError(job->error()); 0076 setErrorText(job->errorText()); 0077 emitResult(); 0078 return; 0079 } 0080 0081 const DistributionListExpandJob *expandJob = qobject_cast<DistributionListExpandJob *>(job); 0082 const QString recipient = expandJob->property("recipient").toString(); 0083 0084 DistributionListExpansionResult result; 0085 result.addresses = expandJob->addresses(); 0086 result.isEmpty = expandJob->isEmpty(); 0087 0088 mDistListExpansionResults.insert(recipient, result); 0089 0090 mDistributionListExpansionJobs--; 0091 if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) { 0092 finishExpansion(); 0093 } 0094 } 0095 0096 void AliasesExpandJob::slotNicknameExpansionDone(KJob *job) 0097 { 0098 if (job->error()) { 0099 setError(job->error()); 0100 setErrorText(job->errorText()); 0101 emitResult(); 0102 return; 0103 } 0104 0105 const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job); 0106 const KContacts::Addressee::List contacts = searchJob->contacts(); 0107 const QString recipient = searchJob->property("recipient").toString(); 0108 0109 for (const KContacts::Addressee &contact : contacts) { 0110 if (contact.nickName().toLower() == recipient.toLower()) { 0111 mNicknameExpansionResults.insert(recipient, contact.fullEmail()); 0112 break; 0113 } 0114 } 0115 0116 mNicknameExpansionJobs--; 0117 if (mDistributionListExpansionJobs == 0 && mNicknameExpansionJobs == 0) { 0118 finishExpansion(); 0119 } 0120 } 0121 0122 void AliasesExpandJob::finishExpansion() 0123 { 0124 for (const QString &recipient : std::as_const(mRecipients)) { 0125 if (recipient.isEmpty()) { 0126 continue; 0127 } 0128 if (!mEmailAddresses.isEmpty()) { 0129 mEmailAddresses += QLatin1StringView(", "); 0130 } 0131 0132 const QString receiver = recipient.trimmed(); 0133 0134 // take prefetched expand distribution list results 0135 const DistributionListExpansionResult result = mDistListExpansionResults.value(recipient); 0136 QString displayName; 0137 QString addrSpec; 0138 QString comment; 0139 0140 if (result.isEmpty) { 0141 KEmailAddress::splitAddress(receiver, displayName, addrSpec, comment); 0142 mEmailAddressOnly.append(addrSpec); 0143 mEmailAddresses += receiver; 0144 mEmptyDistributionLists << receiver; 0145 continue; 0146 } 0147 0148 if (!result.addresses.isEmpty()) { 0149 KEmailAddress::splitAddress(result.addresses, displayName, addrSpec, comment); 0150 mEmailAddressOnly.append(addrSpec); 0151 0152 mEmailAddresses += result.addresses; 0153 continue; 0154 } 0155 0156 // take prefetched expand nick name results 0157 const QString recipientValue = mNicknameExpansionResults.value(recipient); 0158 if (!recipientValue.isEmpty()) { 0159 mEmailAddresses += recipientValue; 0160 KEmailAddress::splitAddress(recipientValue, displayName, addrSpec, comment); 0161 mEmailAddressOnly.append(addrSpec); 0162 0163 continue; 0164 } 0165 0166 // check whether the address is missing the domain part 0167 KEmailAddress::splitAddress(receiver, displayName, addrSpec, comment); 0168 if (!addrSpec.contains(QLatin1Char('@'))) { 0169 if (!mDefaultDomain.isEmpty()) { 0170 mEmailAddresses += KEmailAddress::normalizedAddress(displayName, addrSpec + QLatin1Char('@') + mDefaultDomain, comment); 0171 } else { 0172 mEmailAddresses += MessageCore::StringUtil::guessEmailAddressFromLoginName(addrSpec); 0173 } 0174 } else { 0175 mEmailAddresses += receiver; 0176 } 0177 mEmailAddressOnly.append(addrSpec); 0178 } 0179 0180 emitResult(); 0181 } 0182 0183 QStringList AliasesExpandJob::emailAddressOnly() const 0184 { 0185 return mEmailAddressOnly; 0186 } 0187 0188 #include "moc_aliasesexpandjob.cpp"