Commit 51376b22 authored by Sandro Knauß's avatar Sandro Knauß 🐝
Browse files

Implement Autocrypt-Gossip headers.

parent fdba1eda
......@@ -82,3 +82,47 @@ void AutocryptHeadersJobTest::testAutocryptHeader()
Test::compareFile(referenceFile, QStringLiteral(MAIL_DATA_DIR "/")+referenceFile);
}
void AutocryptHeadersJobTest::testAutocryptGossipHeader()
{
Composer composer;
KMime::Message skeletonMessage;
skeletonMessage.from(true)->from7BitString("Alice <alice@autocrypt.example>");
KMime::Content content;
content.setBody("Hi Bob and Carol,\n"
"\n"
"I wanted to introduce the two of you to each other.\n"
"\n"
"I hope you are both doing well! You can now both \"reply all\" here,\n"
"and the thread will remain encrypted.\n");
auto job = QGpgME::openpgp()->keyListJob(false);
std::vector< GpgME::Key > ownKeys;
job->exec(QStringList(QString::fromLatin1(skeletonMessage.from()[0].addresses()[0])), false, ownKeys);
std::vector< GpgME::Key > keys;
job->exec(QStringList({QStringLiteral("bob@autocrypt.example"), QStringLiteral("carol@autocrypt.example")}), false, keys);
auto aJob = new AutocryptHeadersJob(&composer);
QVERIFY(aJob);
aJob->setContent(&content);
aJob->setSkeletonMessage(&skeletonMessage);
aJob->setRecipientKey(ownKeys[0]);
aJob->setPreferEncrypted(true);
aJob->setGossipKeys(keys);
VERIFYEXEC(aJob);
content.contentType(true)->from7BitString("text/plain");
content.assemble();
auto referenceFile = QStringLiteral("autocryptgossipheader.mbox");
QFile f(referenceFile);
QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
f.write(content.encodedContent());
f.close();
Test::compareFile(referenceFile, QStringLiteral(MAIL_DATA_DIR "/")+referenceFile);
}
......@@ -22,7 +22,7 @@ public Q_SLOTS:
private Q_SLOTS:
void testAutocryptHeader();
void testAutocryptGossipHeader();
};
#endif
Autocrypt-Gossip: addr=bob@autocrypt.example; keydata=
mDMEXEcE6RYJKwYBBAHaRw8BAQdAPPy13Q7Y8w2VPRkksrijrn9o8u59ra1c2CJiHFpbM2G0FWJ
vYkBhdXRvY3J5cHQuZXhhbXBsZYiWBBMWCAA+FiEE8FQeqC0xAKoa3zse4w5v3UWQH4IFAlxHBO
kCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ4w5v3UWQH4IfwAEA3lujohz3N
j9afUnaGUXN7YboIzQsmpgGkN8thyb/slIBAKwdJyg1SurKqHnxy3Wl/DBzOrR12/pN7nScn0+x
4sgBuDgEXEcE6RIKKwYBBAGXVQEFAQEHQJSU7QErtJOYXsIagw2qwnVbt31ooVEx8Xcb476NCbF
jAwEIB4h4BBgWCAAgFiEE8FQeqC0xAKoa3zse4w5v3UWQH4IFAlxHBOkCGwwACgkQ4w5v3UWQH4
LlHQEAlwUBfUU8ORC0RAS/dzlZSEm7+ImY12Wv8QGUCx5zPbUA/3YH84ZOAQDbmV/C+R//0WVNb
Gfav9X5KYmiratYR7oL
Autocrypt-Gossip: addr=carol@autocrypt.example; keydata=
mDMEXEcE6RYJKwYBBAHaRw8BAQdAKiHXLyIgys0xGLa+vS+BLtUDydKd3A1E9DpSozOBdfa0F2N
hcm9sQGF1dG9jcnlwdC5leGFtcGxliJYEExYIAD4WIQSt8CGd+u2e0+MFQA8EcmYYsmQnEgUCXE
cE6QIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAEcmYYsmQnEnQFAQDZjvUBE
80VZkocXiATJ9pU2pPg77ygrcJbiIuHExcmmgEArhI+IzZWmOFQH6QVGsLYQf981GMGDCoV8MyN
hBHCqQ64OARcRwTpEgorBgEEAZdVAQUBAQdAHx6p0V/ki//8CqLOh0EWwqTKyFeHGY4b2c2YFV+
jF3YDAQgHiHgEGBYIACAWIQSt8CGd+u2e0+MFQA8EcmYYsmQnEgUCXEcE6QIbDAAKCRAEcmYYsm
QnEtI2AQDc+PCbtyj9BfNTtqxSD3JMTXlbHDDxuZ84+nXfEVuivQD9Hl5eunlZnm76voE9rgjPw
6h3ReWkUrgbT7fX4YsHdws=
Content-Type: text/plain
Hi Bob and Carol,
I wanted to introduce the two of you to each other.
I hope you are both doing well! You can now both "reply all" here,
and the thread will remain encrypted.
......@@ -42,6 +42,7 @@ public:
KMime::Message *skeletonMessage = nullptr;
bool preferEncrypted = false;
int subJobs = 0;
GpgME::Key recipientKey;
std::vector<GpgME::Key> gossipKeys;
......@@ -163,6 +164,11 @@ void AutocryptHeadersJob::doStart()
Q_ASSERT(job);
connect(job, &QGpgME::ExportJob::result, this, [this, d](const GpgME::Error &error, const QByteArray &keydata) {
d->subJobs--;
if (AutocryptHeadersJob::error()) {
// When the job already has failed do nothing.
return;
}
if (error) {
d->emitGpgError(error);
return;
......@@ -175,8 +181,45 @@ void AutocryptHeadersJob::doStart()
d->fillHeaderData(autocrypt, d->skeletonMessage->from()->addresses()[0], d->preferEncrypted, keydata);
d->skeletonMessage->setHeader(autocrypt);
emitResult();
if (!d->subJobs) {
emitResult();
}
});
foreach(const auto key, d->gossipKeys) {
auto gossipJob = QGpgME::openpgp()->publicKeyExportJob(false);
Q_ASSERT(gossipJob);
connect(gossipJob, &QGpgME::ExportJob::result, this, [this, d, key](const GpgME::Error &error, const QByteArray &keydata) {
d->subJobs--;
if (AutocryptHeadersJob::error()) {
// When the job already has failed do nothing.
return;
}
if (error) {
d->emitGpgError(error);
return;
}
if (keydata.isEmpty()) {
d->emitNotFoundError(key.userID(0).email(), key.primaryFingerprint());
}
auto header = new KMime::Headers::Generic("Autocrypt-Gossip");
d->fillHeaderData(header, key.userID(0).email(), false, keydata);
d->content->appendHeader(header);
if (!d->subJobs) {
emitResult();
}
});
d->subJobs++;
gossipJob->start(QStringList(QString::fromLatin1(key.primaryFingerprint())));
}
d->subJobs++;
job->start(QStringList(QString::fromLatin1(d->recipientKey.primaryFingerprint())));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment