diff --git a/messagecomposer/autotests/messagefactoryngtest.cpp b/messagecomposer/autotests/messagefactoryngtest.cpp --- a/messagecomposer/autotests/messagefactoryngtest.cpp +++ b/messagecomposer/autotests/messagefactoryngtest.cpp @@ -217,8 +217,8 @@ QString ba = QString::fromLatin1("From: foo1 \n" "X-KMail-Identity: %1\n" "Date: %2\n" - "Cc: blo , bli , blu , bly , Bla \n" - "To: Bla \n" + "Cc: blu , bly \n" + "To: blo , bli \n" "Subject: Re: Plain Message Test\n" "Content-Type: text/plain; charset=\"US-ASCII\"\n" "Content-Transfer-Encoding: 8Bit\nMIME-Version: 1.0\n" @@ -265,8 +265,8 @@ QString dateStr = reply.msg->date()->asUnicodeString(); QString ba = QString::fromLatin1("From: another \n" "Date: %1\n" - "Cc: blo , bli , blu , bly \n" - "To: Bla \n" + "Cc: blu , bly \n" + "To: blo , bli \n" "Subject: Re: Plain Message Test\n" "Content-Type: text/plain; charset=\"US-ASCII\"\n" "Content-Transfer-Encoding: 8Bit\nMIME-Version: 1.0\n" diff --git a/messagecomposer/autotests/replystrategytest.cpp b/messagecomposer/autotests/replystrategytest.cpp --- a/messagecomposer/autotests/replystrategytest.cpp +++ b/messagecomposer/autotests/replystrategytest.cpp @@ -266,17 +266,38 @@ << friend1Address << only(defaultAddress) << only(friend2Address) << only(replyAddress) << nobody << QString() << nobody << (int)ReplyAll << defaultAddress << only(replyAddress) << only(friend2Address); + QTest::newRow("ReplyAll, with Mail-Reply-To in original") + << friend1Address << only(defaultAddress) << only(friend2Address) + << only(replyAddress) << nobody << QString() << only(mailReplyAddress) + << (int)ReplyAll << defaultAddress << only(mailReplyAddress) << only(friend2Address); + + // If the original message was _from_ the user _to_ another person (the + // reverse of the usual direction), reply to all goes to the other person. + // Therefore Mail-Reply-To and Reply-To are ignored. + // The reply is assumed to add to the original message. + QTest::newRow("ReplyAll, from default identity to someone") + << defaultAddress << only(friend1Address) << only(friend2Address) + << only(replyAddress) << nobody << QString() << only(mailReplyAddress) + << (int)ReplyAll << defaultAddress << only(friend1Address) << only(friend2Address); + + // If the original message was from one of the user's identities to another + // identity (i.e., between two of the user's mail accounts), reply to all + // goes back to the sending identity. + QTest::newRow("ReplyAll, between identities") + << defaultAddress << only(nondefaultAddress) << only(friend2Address) + << nobody << nobody << QString() << nobody + << (int)ReplyAll << nondefaultAddress << only(defaultAddress) << only(friend2Address); // If the original passed through a mailing list, ReplyAll replies to the - // list, preferring Mail-Followup-To over List-Post as the list address. + // list. // It CCs the author, using Mail-Reply-To, Reply-To, or From (in that order). QTest::newRow("ReplyAll, from list with List-Post") << friend1Address << only(nondefaultAddress) << only(friend2Address) << nobody << nobody << listAddress << nobody << (int)ReplyAll << nondefaultAddress << only(listAddress) << both(friend1Address, friend2Address); // If Reply-To is the same as List-Post, ReplyAll ignores it and uses - // From, because the mailing list munged Reply-To. + // From for the author's address, because the mailing list munged Reply-To. QTest::newRow("ReplyAll, from list that munges Reply-To") << friend1Address << only(defaultAddress) << nobody << only(listAddress) << nobody << listAddress << nobody diff --git a/messagecomposer/src/helper/messagefactoryng.cpp b/messagecomposer/src/helper/messagefactoryng.cpp --- a/messagecomposer/src/helper/messagefactoryng.cpp +++ b/messagecomposer/src/helper/messagefactoryng.cpp @@ -229,26 +229,21 @@ KMime::Types::Mailbox::List recipients; KMime::Types::Mailbox::List ccRecipients; - QString sender; - if (auto hrd = m_origMsg->sender(false)) { - sender = hrd->asUnicodeString(); - } - // add addresses from the Reply-To header to the list of recipients - if (!replyToList.isEmpty()) { - recipients = replyToList; - - // strip all possible mailing list addresses from the list of Reply-To addresses - for (const KMime::Types::Mailbox &mailbox : qAsConst(m_mailingListAddresses)) { - foreach (const KMime::Types::Mailbox &recipient, recipients) { //Don't use for(...:...) - if (mailbox == recipient) { - recipients.removeAll(recipient); + if (!m_mailingListAddresses.isEmpty()) { + // this is a mailing list message + // add addresses from the Reply-To header to the list of recipients + if (!replyToList.isEmpty()) { + recipients = replyToList; + + // strip all possible mailing list addresses from the list of Reply-To addresses + for (const KMime::Types::Mailbox &mailbox : qAsConst(m_mailingListAddresses)) { + foreach (const KMime::Types::Mailbox &recipient, recipients) { //Don't use for(...:...) + if (mailbox == recipient) { + recipients.removeAll(recipient); + } } } } - } - bool stripMyAddresses = true; - if (!m_mailingListAddresses.isEmpty()) { - // this is a mailing list message if (recipients.isEmpty() && !m_origMsg->from()->asUnicodeString().isEmpty()) { // The sender didn't set a Reply-to address, so we add the From // address to the list of CC recipients. @@ -259,27 +254,29 @@ // if it is a mailing list, add the posting address recipients.prepend(m_mailingListAddresses[ 0 ]); } else { - const QString fromAddress = m_origMsg->from()->asUnicodeString(); - if (!fromAddress.isEmpty()) { - if (!sender.isEmpty() && m_identityManager->thatIsMe(fromAddress)) { - // strip all my addresses from the list of recipients - toList = recipients; - toList += m_origMsg->from()->mailboxes(); - stripMyAddresses = false; - } else { - // this is a normal message - if (recipients.isEmpty()) { - // in case of replying to a normal message only then add the From - // address to the list of recipients if there was no Reply-to address - recipients += m_origMsg->from()->mailboxes(); - qCDebug(MESSAGECOMPOSER_LOG) << "Added" << m_origMsg->from()->asUnicodeString() << "to the list of recipients"; - } - } + // Doesn't seem to be a mailing list. + auto originalFromList = m_origMsg->from()->mailboxes(); + auto originalToList = m_origMsg->to()->mailboxes(); + + if (m_identityManager->thatIsMe(KMime::Types::Mailbox::listToUnicodeString(originalFromList)) + && !m_identityManager->thatIsMe(KMime::Types::Mailbox::listToUnicodeString(originalToList)) + ) { + // Sender seems to be one of our own identities and recipient is not, + // so we assume that this is a reply to a "sent" mail where the user + // wants to add additional information for the recipient. + recipients = originalToList; + } else { + // "Normal" case: reply to sender. + recipients = authorMailboxes(m_origMsg, m_mailingListAddresses); } } - if (stripMyAddresses) { - // strip all my addresses from the list of recipients - toList = stripMyAddressesFromAddressList(recipients, m_identityManager); + + // strip all my addresses from the list of recipients + toList = stripMyAddressesFromAddressList(recipients, m_identityManager); + + // ... unless the list contains only my addresses (reply to self) + if (toList.isEmpty() && !recipients.isEmpty()) { + toList << recipients.first(); } // merge To header and CC header into a list of CC recipients @@ -303,9 +300,7 @@ if (!ccRecipients.isEmpty()) { // strip all my addresses from the list of CC recipients - if (stripMyAddresses) { - ccRecipients = stripMyAddressesFromAddressList(ccRecipients, m_identityManager); - } + ccRecipients = stripMyAddressesFromAddressList(ccRecipients, m_identityManager); // in case of a reply to self, toList might be empty. if that's the case // then propagate a cc recipient to To: (if there is any). @@ -319,10 +314,6 @@ } } - if (toList.isEmpty() && !recipients.isEmpty()) { - // reply to self without other recipients - toList << recipients.at(0); - } break; } case MessageComposer::ReplyAuthor: