diff --git a/lib/mu-message-contact.cc b/lib/mu-message-contact.cc index 64e252a9..c7c50e93 100644 --- a/lib/mu-message-contact.cc +++ b/lib/mu-message-contact.cc @@ -18,11 +18,13 @@ */ #include "mu-message-contact.hh" +#include "mu-message.hh" + #include #include 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 "); @@ -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 , " "\tGhi "; - 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()); } diff --git a/lib/mu-message-contact.hh b/lib/mu-message-contact.hh index 298bc680..a1742287 100644 --- a/lib/mu-message-contact.hh +++ b/lib/mu-message-contact.hh @@ -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 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 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 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; * 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; */ 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 { } }; - - - #endif /* MU_MESSAGE_CONTACT_HH__ */ diff --git a/lib/mu-msg-sexp.cc b/lib/mu-msg-sexp.cc index b27080db..dafc8593 100644 --- a/lib/mu-msg-sexp.cc +++ b/lib/mu-msg-sexp.cc @@ -19,7 +19,7 @@ #include #include -#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("?", - 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; + using ContactPair = std::pair; constexpr std::array 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 */ diff --git a/lib/mu-msg.cc b/lib/mu-msg.cc index 1dded768..40183ac7 100644 --- a/lib/mu-msg.cc +++ b/lib/mu-msg.cc @@ -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 field_id) { typedef const char*(*AddressFunc)(MuMsg*); using AddressInfo = std::pair; 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 {}; diff --git a/lib/mu-msg.hh b/lib/mu-msg.hh index 8dbf2383..80a220c2 100644 --- a/lib/mu-msg.hh +++ b/lib/mu-msg.hh @@ -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 field_id={}); /** * create a 'display contact' from an email header To/Cc/Bcc/From-type address * ie., turn