-
Notifications
You must be signed in to change notification settings - Fork 0
/
unsubscribemanager.cpp
190 lines (168 loc) · 5.08 KB
/
unsubscribemanager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <KLocalizedString>
#include "unsubscribe_debug.h"
#include "unsubscribemanager.h"
#include "oneclickunsubscribejob.h"
using namespace MessageViewer;
UnsubscribeManager::UnsubscribeManager(QObject *parent)
: QObject(parent),
mDkimMgr(DKIMManager(this))
{
connect(&mDkimMgr, &DKIMManager::result, this, &UnsubscribeManager::getDkimResult);
}
UnsubscribeManager::~UnsubscribeManager() = default;
void UnsubscribeManager::reset()
{
mDKIMValid = false;
mItemId = -1;
mPostUrl = QUrl();
mMessage = nullptr;
}
void UnsubscribeManager::setMessageItem(const Akonadi::Item &item)
{
if (item.id() == mItemId)
{
// We already have this item, do nothing
return;
}
else if (mItemId != -1)
{
// reset wasn't called first, so call it for them
this->reset();
}
// First, we have to have a KMime::Message::Ptr
if (item.hasPayload<KMime::Message::Ptr>())
{
mMessage = item.payload<KMime::Message::Ptr>();
if (mMessage == nullptr)
{
// Sometimes we get nullptr even though item.hasPayload() was true...
qCInfo(UnsubscribePlugin) << "Can't get current email";
return;
}
mItemId = item.id();
// Check if we even have Unsubscribe info
mList = MessageCore::MailingList::detect(mMessage);
}
else
{
qWarning(UnsubscribePlugin) << "Received email doesn't seem to be an email";
}
// Don't bother checking DKIM if we don't have an unsubscribe URL, or if we
// don't have DKIM enabled
if (!(getUrl().isEmpty()) && MessageViewerSettings::self()->enabledDkim())
{
mDkimMgr.checkDKim(item);
}
}
bool UnsubscribeManager::hasMessage()
{
return !(mMessage == nullptr);
}
void UnsubscribeManager::getDkimResult(const MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult &checkResult, Akonadi::Item::Id id)
{
if (id == mItemId)
{
mDKIMValid = checkResult.isValid();
qCDebug(UnsubscribePlugin) << "Got DKIM result! Valid:" << mDKIMValid;
}
else
{
qCDebug(UnsubscribePlugin) << "Got DKIM result for wrong ID! Wanted" << mItemId << "but got" << id;
}
}
UnsubscribeManager::Status
UnsubscribeManager::unsubscribeStatus()
{
if (mMessage != nullptr && mList.features().testFlag(MessageCore::MailingList::Unsubscribe))
{
if (!oneClickUrl().isEmpty())
{
// One-Click requires List-Unsubscribe-Post
if (mMessage->hasHeader(LIST_UNSUBSCRIBE_POST_HDR))
{
if (MessageViewerSettings::self()->enabledDkim() &&
!mDKIMValid)
{
return UnsubscribeManager::InvalidOneClick;
}
return UnsubscribeManager::ValidOneClick;
}
}
return UnsubscribeManager::NoOneClick;
}
return UnsubscribeManager::None;
}
void UnsubscribeManager::doOneClick()
{
auto status = unsubscribeStatus();
if (status == UnsubscribeManager::InvalidOneClick || status == UnsubscribeManager::ValidOneClick)
{
auto job = new OneClickUnsubscribeJob(mPostUrl, this);
connect(job, &OneClickUnsubscribeJob::result, this, &UnsubscribeManager::checkResult);
job->start();
}
}
QUrl UnsubscribeManager::oneClickUrl()
{
if (mPostUrl.isEmpty() && mList.features().testFlag(MessageCore::MailingList::Unsubscribe))
{
foreach (QUrl url, mList.unsubscribeUrls())
{
// Per the RFC, there should only be one HTTPS URL. So grab the
// first one we find
if (url.scheme() == QStringLiteral("https"))
{
mPostUrl = url;
break;
}
}
}
return mPostUrl;
}
QUrl UnsubscribeManager::getUrl()
{
// TODO: Maybe this should be customizable.
// The theory is that HTTPS is most secure, mailto is more likely to be
// secure (MTAs often use TLS these days), and http as last resort. I really
// hope nobody's requesting unsubscribe over IRC...
const QStringList protocols = {"https", "mailto", "http"};
if (!mPostUrl.isEmpty())
{
return mPostUrl;
}
else
{
foreach (QString scheme, protocols)
{
foreach (QUrl url, mList.unsubscribeUrls())
{
if (url.scheme() == scheme)
{
return url;
}
}
}
}
return QUrl();
}
void UnsubscribeManager::checkResult(const Result &result)
{
bool isSuccess = false;
QString resultStr;
switch (result.Type)
{
case Result::None:
isSuccess = true;
break;
case Result::NetworkError:
resultStr = i18n("Unable to send unsubscribe request: %1", result.ErrorString);
break;
case Result::SslError:
resultStr = i18n("Got one or more SSL errors: %1", result.ErrorString);
break;
default:
resultStr = i18n("Plugin hit an unreachable point");
}
Q_EMIT oneClickResult(isSuccess, resultStr);
}
#include "moc_unsubscribemanager.cpp"