message: contact: remove ::Type, use Field

Don't need a special Type {} in Contact, when we have more-or-less the same info
in Field.
This commit is contained in:
Dirk-Jan C. Binnema
2022-03-19 18:38:30 +02:00
parent a23c99ff7e
commit d4285975b3
5 changed files with 76 additions and 111 deletions

View File

@ -18,11 +18,13 @@
*/
#include "mu-message-contact.hh"
#include "mu-message.hh"
#include <gmime/gmime.h>
#include <glib.h>
using namespace Mu;
using namespace Mu::Message;
std::string
MessageContact::display_name() const
@ -35,8 +37,7 @@ MessageContact::display_name() const
Mu::MessageContacts
Mu::make_message_contacts(InternetAddressList* addr_lst,
MessageContact::Type type,
::time_t message_date)
Field::Id field_id, ::time_t message_date)
{
MessageContacts contacts;
size_t num{};
@ -59,7 +60,7 @@ Mu::make_message_contacts(InternetAddressList* addr_lst,
continue;
contacts.push_back(MessageContact{email, name ? name : "",
type, message_date});
field_id, message_date});
++num;
}
@ -69,7 +70,7 @@ Mu::make_message_contacts(InternetAddressList* addr_lst,
Mu::MessageContacts
Mu::make_message_contacts(const std::string& addrs,
MessageContact::Type type,
Field::Id field_id,
::time_t message_date)
{
auto addr_list = internet_address_list_parse(NULL, addrs.c_str());
@ -78,7 +79,7 @@ Mu::make_message_contacts(const std::string& addrs,
return {};
}
auto contacts{make_message_contacts(addr_list, type, message_date)};
auto contacts{make_message_contacts(addr_list, field_id, message_date)};
g_object_unref(addr_list);
return contacts;
@ -109,13 +110,13 @@ test_ctor_foo()
MessageContact c{
"foo@example.com",
"Foo Bar",
MessageContact::Type::Bcc,
Field::Id::Bcc,
1645214647
};
assert_equal(c.email, "foo@example.com");
assert_equal(c.name, "Foo Bar");
g_assert_true(c.type == MessageContact::Type::Bcc);
g_assert_true(c.field_id == Field::Id::Bcc);
g_assert_cmpuint(c.message_date,==,1645214647);
assert_equal(c.display_name(), "Foo Bar <foo@example.com>");
@ -178,12 +179,12 @@ test_make_contacts()
internet_address_list_parse(NULL, str)};
g_assert_true(lst);
const auto addrs{make_message_contacts(lst, MessageContact::Type::Cc, 54321 )};
const auto addrs{make_message_contacts(lst, Field::Id::Cc, 54321 )};
g_object_unref(lst);
g_assert_cmpuint(addrs.size(),==,3);
const auto addrs2{make_message_contacts(str, MessageContact::Type::To, 12345 )};
const auto addrs2{make_message_contacts(str, Field::Id::To, 12345 )};
g_assert_cmpuint(addrs2.size(),==,3);
assert_equal(addrs2[0].name, "Abc");
@ -201,7 +202,7 @@ test_make_contacts_2()
"De\nf <baa@example.com>, "
"\tGhi <zzz@example.com>";
const auto addrs2{make_message_contacts(str, MessageContact::Type::Bcc, 12345 )};
const auto addrs2{make_message_contacts(str, Field::Id::Bcc, 12345 )};
g_assert_cmpuint(addrs2.size(),==,3);
assert_equal(addrs2[0].name, "Äbc");
@ -221,7 +222,7 @@ test_make_contacts_err()
InternetAddressList *lst{ internet_address_list_parse(NULL, "")};
g_assert_false(lst);
const auto addrs{make_message_contacts("", MessageContact::Type::To, 77777)};
const auto addrs{make_message_contacts("", Field::Id::To, 77777)};
g_assert_true(addrs.empty());
}

View File

@ -44,31 +44,19 @@ namespace Mu {
*/
size_t lowercase_hash(const std::string& s);
struct MessageContact {
/**
* Contact types
*/
enum struct Type {
To, /**< To recipient */
From, /**< Sender */
Cc, /**< Cc recipient */
Bcc, /**< Bcc recipient */
ReplyTo, /**< Reply-To wannabe recipient */
Unknown, /**< Unknown type */
};
/**
* Construct a new MessageContact
*
* @param email_ email address
* @param name_ name or empty
* @param type_ contact type
* @param field_id_ contact field id, or {}
* @param message_date_ data for the message for this contact
*/
MessageContact(const std::string& email_, const std::string& name_ = "",
Type type_ = Type::Unknown, time_t message_date_ = 0)
: email{email_}, name{name_}, type{type_},
std::optional<MessageField::Id> field_id_ = {},
time_t message_date_ = 0)
: email{email_}, name{name_}, field_id{field_id_},
message_date{message_date_}, personal{}, frequency{1}, tstamp{}
{ cleanup_name(); }
@ -85,7 +73,7 @@ struct MessageContact {
MessageContact(const std::string& email_, const std::string& name_,
time_t message_date_, bool personal_, size_t freq_,
int64_t tstamp_)
: email{email_}, name{name_}, type{Type::Unknown},
: email{email_}, name{name_}, field_id{},
message_date{message_date_}, personal{personal_}, frequency{freq_},
tstamp{tstamp_}
{ cleanup_name();}
@ -126,39 +114,18 @@ struct MessageContact {
return cached_hash;
}
/**
* Get the MessageField for this contact-type, if any.
*
* @return the message-field or nullopt.
*/
constexpr std::optional<MessageField> const field() {
switch(type){
case Type::From:
return message_field(MessageField::Id::From);
case Type::To:
return message_field(MessageField::Id::To);
case Type::Cc:
return message_field(MessageField::Id::Cc);
case Type::Bcc:
return message_field(MessageField::Id::Bcc);
default:
return std::nullopt;
}
}
/*
* data members
*/
std::string email; /**< Email address for this contact.Not empty */
std::string name; /**< Name for this contact; can be empty. */
Type type{Type::Unknown}; /**< Type of contact */
::time_t message_date; /**< date of the message from which the
* contact originates */
bool personal; /**< A personal message? */
size_t frequency; /**< Frequency of this contact */
int64_t tstamp; /**< Timestamp for this contact */
std::string email; /**< Email address for this contact.Not empty */
std::string name; /**< Name for this contact; can be empty. */
std::optional<MessageField::Id> field_id; /**< Field Id of contact or nullopt */
::time_t message_date; /**< date of the message from which the
* contact originates */
bool personal; /**< A personal message? */
size_t frequency; /**< Frequency of this contact */
int64_t tstamp; /**< Timestamp for this contact */
private:
void cleanup_name() { // replace control characters by spaces.
@ -174,7 +141,7 @@ using MessageContacts = std::vector<MessageContact>;
* Create a sequence of MessageContact objects from an InternetAddressList
*
* @param addr_lst an address list
* @param type the type of addresses
* @param field_id the field_id for message field for these addresses
* @param message_date the date of the message from which the InternetAddressList
* originates.
*
@ -182,20 +149,20 @@ using MessageContacts = std::vector<MessageContact>;
*/
MessageContacts
make_message_contacts(/*const*/ struct _InternetAddressList* addr_lst,
MessageContact::Type type, ::time_t message_date);
MessageField::Id field_id, ::time_t message_date);
/**
* Create a sequence of MessageContact objects from an InternetAddressList
*
* @param addrs a string with one more valid addresses (as per internet_address_list_parse())
* @param type the type of addresses
* @param field_id the field_id for message field for these addresses
* @param message_date the date of the message from which the addresses originate
*
* @return a sequence of MessageContact objects.
*/
MessageContacts
make_message_contacts(const std::string& addrs,
MessageContact::Type type, ::time_t message_date);
MessageField::Id field_id, ::time_t message_date);
} // namespace Mu
/**
@ -207,7 +174,4 @@ template<> struct std::hash<Mu::MessageContact> {
}
};
#endif /* MU_MESSAGE_CONTACT_HH__ */

View File

@ -19,7 +19,7 @@
#include <string.h>
#include <ctype.h>
#include "mu-message-flags.hh"
#include "mu-message.hh"
#include "mu-query-results.hh"
#include "utils/mu-str.h"
#include "mu-msg.hh"
@ -27,6 +27,7 @@
#include "mu-maildir.hh"
using namespace Mu;
using namespace Mu::Message;
static void
add_prop_nonempty(Sexp::List& list, const char* elm, const GSList* str_lst)
@ -76,9 +77,9 @@ add_list_post(Sexp::List& list, MuMsg* msg)
return;
rx = g_regex_new("<?mailto:([a-z0-9!@#$%&'*+-/=?^_`{|}~]+)>?",
G_REGEX_CASELESS,
(GRegexMatchFlags)0,
NULL);
G_REGEX_CASELESS,
(GRegexMatchFlags)0,
NULL);
g_return_if_fail(rx);
if (g_regex_match(rx, list_post, (GRegexMatchFlags)0, &minfo)) {
@ -94,22 +95,22 @@ add_list_post(Sexp::List& list, MuMsg* msg)
static void
add_contacts(Sexp::List& list, MuMsg* msg)
{
using ContactPair = std::pair<MessageContact::Type, std::string_view>;
using ContactPair = std::pair<Field::Id, std::string_view>;
constexpr std::array<ContactPair, 5> contact_types = {{
{ MessageContact::Type::From, ":from" },
{ MessageContact::Type::To, ":to" },
{ MessageContact::Type::Cc, ":cc" },
{ MessageContact::Type::ReplyTo, ":reply-to" },
{ MessageContact::Type::Bcc, ":bcc" },
{ Field::Id::From, ":from" },
{ Field::Id::To, ":to" },
{ Field::Id::Cc, ":cc" },
// { Field::Id::ReplyTo, ":reply-to" },
{ Field::Id::Bcc, ":bcc" },
}};
for (auto&& contact_type : contact_types) {
const auto contacts{mu_msg_get_contacts(msg, contact_type.first)};
if (contacts.empty())
continue;
Sexp::List c_list;
Sexp::List c_list;
for (auto&& contact: contacts)
c_list.add(make_contact_sexp(contact));
@ -151,7 +152,7 @@ get_temp_file(MuMsg* msg, MuMsgOptions opts, unsigned index)
errexit:
g_warning("failed to save mime part: %s",
err->message ? err->message : "something went wrong");
err->message ? err->message : "something went wrong");
g_clear_error(&err);
g_free(path);
@ -216,11 +217,11 @@ make_part_types(MuMsgPartType ptype)
MuMsgPartType ptype;
const char* name;
} ptypes[] = {{MU_MSG_PART_TYPE_LEAF, "leaf"},
{MU_MSG_PART_TYPE_MESSAGE, "message"},
{MU_MSG_PART_TYPE_INLINE, "inline"},
{MU_MSG_PART_TYPE_ATTACHMENT, "attachment"},
{MU_MSG_PART_TYPE_SIGNED, "signed"},
{MU_MSG_PART_TYPE_ENCRYPTED, "encrypted"}};
{MU_MSG_PART_TYPE_MESSAGE, "message"},
{MU_MSG_PART_TYPE_INLINE, "inline"},
{MU_MSG_PART_TYPE_ATTACHMENT, "attachment"},
{MU_MSG_PART_TYPE_SIGNED, "signed"},
{MU_MSG_PART_TYPE_ENCRYPTED, "encrypted"}};
Sexp::List list;
for (auto u = 0U; u != G_N_ELEMENTS(ptypes); ++u)
@ -234,8 +235,8 @@ static void
each_part(MuMsg* msg, MuMsgPart* part, PartInfo* pinfo)
{
auto mimetype = format("%s/%s",
part->type ? part->type : "application",
part->subtype ? part->subtype : "octet-stream");
part->type ? part->type : "application",
part->subtype ? part->subtype : "octet-stream");
auto maybe_attach = Sexp::make_symbol(mu_msg_part_maybe_attachment(part) ? "t" : "nil");
Sexp::List partlist;
@ -285,7 +286,7 @@ add_message_file_parts(Sexp::List& items, MuMsg* msg, MuMsgOptions opts)
GError* err{NULL};
if (!mu_msg_load_msg_file(msg, &err)) {
g_warning("failed to load message file: %s",
err ? err->message : "some error occurred");
err ? err->message : "some error occurred");
g_clear_error(&err);
return;
}
@ -301,8 +302,8 @@ add_message_file_parts(Sexp::List& items, MuMsg* msg, MuMsgOptions opts)
add_prop_nonempty(items, ":user-agent", str);
add_prop_nonempty(items,
":body-txt-params",
mu_msg_get_body_text_content_type_parameters(msg, opts));
":body-txt-params",
mu_msg_get_body_text_content_type_parameters(msg, opts));
add_prop_nonempty(items, ":body-txt", mu_msg_get_body_text(msg, opts));
add_prop_nonempty(items, ":body-html", mu_msg_get_body_html(msg, opts));
}
@ -358,7 +359,7 @@ Mu::msg_to_sexp_list(MuMsg* msg, unsigned docid, MuMsgOptions opts)
add_prop_nonempty(items, ":maildir", mu_msg_get_maildir(msg));
items.add_prop(":priority",
Sexp::make_symbol_sv(message_priority_name(mu_msg_get_prio(msg))));
Sexp::make_symbol_sv(message_priority_name(mu_msg_get_prio(msg))));
/* in the no-headers-only case (see below) we get a more complete list of contacts, so no
* need to get them here if that's the case */

View File

@ -624,40 +624,40 @@ get_all_contacts(MuMsg *self)
{
MessageContacts contacts;
for (auto&& mtype : { MessageContact::Type::From, MessageContact::Type::To,
MessageContact::Type::Cc, MessageContact::Type::ReplyTo,
MessageContact::Type::Bcc}) {
auto type_contacts{mu_msg_get_contacts(self, mtype)};
message_field_for_each([&](const auto& field){
if (!field.is_contact())
return;
auto type_contacts{mu_msg_get_contacts(self, field.id)};
contacts.reserve(contacts.size() + type_contacts.size());
contacts.insert(contacts.end(), type_contacts.begin(), type_contacts.end());
}
contacts.insert(contacts.end(), type_contacts.begin(),
type_contacts.end());
});
return contacts;
}
Mu::MessageContacts
Mu::mu_msg_get_contacts(MuMsg *self, MessageContact::Type mtype)
Mu::mu_msg_get_contacts(MuMsg *self, std::optional<MessageField::Id> field_id)
{
typedef const char*(*AddressFunc)(MuMsg*);
using AddressInfo = std::pair<GMimeAddressType, AddressFunc>;
g_return_val_if_fail(self, MessageContacts{});
if (mtype == MessageContact::Type::Unknown)
g_return_val_if_fail(!field_id || message_field(*field_id).is_contact(),
MessageContacts{});
if (!field_id)
return get_all_contacts(self);
const auto info = std::invoke([&]()->AddressInfo {
switch (mtype) {
case MessageContact::Type::From:
switch (*field_id) {
case MessageField::Id::From:
return { GMIME_ADDRESS_TYPE_FROM, mu_msg_get_from };
case MessageContact::Type::To:
case MessageField::Id::To:
return { GMIME_ADDRESS_TYPE_TO, mu_msg_get_to };
case MessageContact::Type::Cc:
case MessageField::Id::Cc:
return { GMIME_ADDRESS_TYPE_CC, mu_msg_get_cc };
case MessageContact::Type::ReplyTo:
return { GMIME_ADDRESS_TYPE_REPLY_TO, {} };
case MessageContact::Type::Bcc:
case MessageField::Id::Bcc:
return { GMIME_ADDRESS_TYPE_BCC, mu_msg_get_bcc };
default:
throw std::logic_error("bug");
@ -668,10 +668,10 @@ Mu::mu_msg_get_contacts(MuMsg *self, MessageContact::Type mtype)
if (self->_file) {
if (auto&& lst{g_mime_message_get_addresses(
self->_file->_mime_msg, info.first)}; lst)
return make_message_contacts(lst, mtype, mdate);
return make_message_contacts(lst, *field_id, mdate);
} else if (info.second) {
if (auto&& lst_str{info.second(self)}; lst_str)
return make_message_contacts(lst_str, mtype, mdate);
return make_message_contacts(lst_str, *field_id, mdate);
}
return {};

View File

@ -441,13 +441,12 @@ bool mu_msg_move_to_maildir(MuMsg* msg,
* Get a sequence with contacts of the given type for this message.
*
* @param msg a valid MuMsg* instance
* @param mtype the contact type; with Type::Unknown, get _all_ types.
* @param field_id the contact field or none; if none get _all_ contact types.
*
* @return a sequence
*/
Mu::MessageContacts mu_msg_get_contacts (MuMsg *self,
MessageContact::Type mtype=MessageContact::Type::Unknown);
std::optional<MessageField::Id> field_id={});
/**
* create a 'display contact' from an email header To/Cc/Bcc/From-type address
* ie., turn