[evolution] I#1639 - Filter messages by condition if sender is in address book
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] I#1639 - Filter messages by condition if sender is in address book
- Date: Fri, 24 Sep 2021 12:12:48 +0000 (UTC)
commit 6384787e2613b837936478a6072ecb4f8c64da00
Author: Milan Crha <mcrha redhat com>
Date: Fri Sep 24 14:12:10 2021 +0200
I#1639 - Filter messages by condition if sender is in address book
Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1639
src/mail/e-mail-ui-session.c | 131 +++++++++++++++++++++++++++-----
src/mail/filtertypes.xml.in | 17 +++++
src/mail/searchtypes.xml.in | 17 +++++
src/mail/vfoldertypes.xml.in | 17 +++++
src/modules/mail/e-mail-shell-backend.c | 50 ++++++++++++
src/modules/mail/e-mail-shell-backend.h | 2 +
6 files changed, 214 insertions(+), 20 deletions(-)
---
diff --git a/src/mail/e-mail-ui-session.c b/src/mail/e-mail-ui-session.c
index 21a37b6f02..f76e24f287 100644
--- a/src/mail/e-mail-ui-session.c
+++ b/src/mail/e-mail-ui-session.c
@@ -619,6 +619,111 @@ mail_ui_session_lookup_addressbook (CamelSession *session,
return known_address;
}
+static gboolean
+mail_ui_session_check_book_contains_sync (EMailUISession *ui_session,
+ ESource *source,
+ const gchar *email_address,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EPhotoCache *photo_cache;
+ EClientCache *client_cache;
+ EClient *client;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (E_IS_MAIL_UI_SESSION (ui_session), FALSE);
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (email_address != NULL, FALSE);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return FALSE;
+
+ if (!e_source_get_enabled (source))
+ return FALSE;
+
+ /* XXX EPhotoCache holds a reference on EClientCache, which
+ * we need. EMailUISession should probably hold its own
+ * EClientCache reference, but this will do for now. */
+ photo_cache = e_mail_ui_session_get_photo_cache (ui_session);
+ client_cache = e_photo_cache_ref_client_cache (photo_cache);
+
+ client = e_client_cache_get_client_sync (
+ client_cache, source,
+ E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) 10,
+ cancellable, error);
+
+ if (client != NULL) {
+ success = e_book_client_contains_email_sync (
+ E_BOOK_CLIENT (client), email_address,
+ cancellable, error);
+
+ g_object_unref (client);
+ }
+
+ g_object_unref (client_cache);
+
+ return success;
+}
+
+static gboolean
+mail_ui_session_addressbook_contains_sync (CamelSession *session,
+ const gchar *book_uid,
+ const gchar *email_address,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EMailUISession *ui_session = E_MAIL_UI_SESSION (session);
+ GError *local_error = NULL;
+ GList *books = NULL, *link;
+ gboolean found = FALSE;
+
+ if (g_strcmp0 (book_uid, CAMEL_SESSION_BOOK_UID_ANY) == 0) {
+ books = e_source_registry_list_enabled (ui_session->priv->registry,
E_SOURCE_EXTENSION_ADDRESS_BOOK);
+ } else if (g_strcmp0 (book_uid, CAMEL_SESSION_BOOK_UID_COMPLETION) == 0) {
+ GList *next = NULL;
+
+ books = e_source_registry_list_enabled (ui_session->priv->registry,
E_SOURCE_EXTENSION_ADDRESS_BOOK);
+
+ for (link = books; link; link = next) {
+ ESource *source = link->data;
+
+ next = g_list_next (link);
+
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTOCOMPLETE) &&
+ !e_source_autocomplete_get_include_me (E_SOURCE_AUTOCOMPLETE
(e_source_get_extension (source, E_SOURCE_EXTENSION_AUTOCOMPLETE)))) {
+ g_object_unref (source);
+ books = g_list_delete_link (books, link);
+ }
+ }
+ } else {
+ ESource *source;
+
+ source = e_source_registry_ref_source (ui_session->priv->registry, book_uid);
+ if (source) {
+ found = mail_ui_session_check_book_contains_sync (ui_session, source, email_address,
cancellable, error);
+ g_object_unref (source);
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("Book '%s' not found"),
book_uid);
+ }
+ }
+
+ for (link = books; link && !found && !g_cancellable_is_cancelled (cancellable); link = g_list_next
(link)) {
+ ESource *source = link->data;
+
+ /* use the error from the first book, if looking in more books */
+ found = mail_ui_session_check_book_contains_sync (ui_session, source, email_address,
cancellable, local_error ? NULL : &local_error);
+ }
+
+ g_list_free_full (books, g_object_unref);
+
+ if (!found && local_error)
+ g_propagate_error (error, local_error);
+ else
+ g_clear_error (&local_error);
+
+ return found;
+}
+
static void
mail_ui_session_user_alert (CamelSession *session,
CamelService *service,
@@ -999,6 +1104,7 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
session_class->remove_service = mail_ui_session_remove_service;
session_class->get_filter_driver = mail_ui_session_get_filter_driver;
session_class->lookup_addressbook = mail_ui_session_lookup_addressbook;
+ session_class->addressbook_contains_sync = mail_ui_session_addressbook_contains_sync;
session_class->user_alert = mail_ui_session_user_alert;
session_class->trust_prompt = mail_ui_session_trust_prompt;
session_class->authenticate_sync = mail_ui_session_authenticate_sync;
@@ -1209,10 +1315,8 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
EPhotoCache *photo_cache;
EClientCache *client_cache;
ESourceRegistry *registry;
- EBookQuery *book_query;
GList *list, *link;
const gchar *email_address = NULL;
- gchar *book_query_string;
gboolean known_address = FALSE;
gboolean success = FALSE;
@@ -1243,11 +1347,6 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
client_cache = e_photo_cache_ref_client_cache (photo_cache);
registry = e_client_cache_ref_registry (client_cache);
- book_query = e_book_query_field_test (
- E_CONTACT_EMAIL, E_BOOK_QUERY_IS, email_address);
- book_query_string = e_book_query_to_string (book_query);
- e_book_query_unref (book_query);
-
if (check_local_only) {
ESource *source;
@@ -1263,7 +1362,6 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
for (link = list; link != NULL && !g_cancellable_is_cancelled (cancellable); link = g_list_next
(link)) {
ESource *source = E_SOURCE (link->data);
EClient *client;
- GSList *uids = NULL;
GError *local_error = NULL;
/* Skip disabled sources. */
@@ -1290,31 +1388,24 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
break;
}
- success = e_book_client_get_contacts_uids_sync (
- E_BOOK_CLIENT (client), book_query_string,
- &uids, cancellable, &local_error);
+ success = e_book_client_contains_email_sync (
+ E_BOOK_CLIENT (client), email_address,
+ cancellable, &local_error);
g_object_unref (client);
if (!success) {
- g_warn_if_fail (uids == NULL);
-
/* ignore book-specific errors here and continue with the next */
g_clear_error (&local_error);
continue;
}
- if (uids != NULL) {
- g_slist_free_full (uids, (GDestroyNotify) g_free);
- known_address = TRUE;
- break;
- }
+ known_address = TRUE;
+ break;
}
g_list_free_full (list, (GDestroyNotify) g_object_unref);
- g_free (book_query_string);
-
g_object_unref (registry);
g_object_unref (client_cache);
diff --git a/src/mail/filtertypes.xml.in b/src/mail/filtertypes.xml.in
index c5cec3f601..26c7e0ca0e 100644
--- a/src/mail/filtertypes.xml.in
+++ b/src/mail/filtertypes.xml.in
@@ -679,6 +679,23 @@
<input type="folder" name="folder"/>
</part>
+ <part name="addressbook">
+ <_title>Address book</_title>
+ <input type="optionlist" name="book">
+ <dynamic func="e_mail_addressbook_get_filter_options"/>
+ </input>
+ <input type="optionlist" name="compare-type">
+ <option value="contains-sender">
+ <_title>contains Sender</_title>
+ <code>(addressbook-contains ${book} "From")</code>
+ </option>
+ <option value="not-contains-sender">
+ <_title>does not contain Sender</_title>
+ <code>(not (addressbook-contains ${book} "From"))</code>
+ </option>
+ </input>
+ </part>
+
<part name="all">
<_title>Match All</_title>
<code>#t</code>
diff --git a/src/mail/searchtypes.xml.in b/src/mail/searchtypes.xml.in
index d0362d59dd..ff078eb6fb 100644
--- a/src/mail/searchtypes.xml.in
+++ b/src/mail/searchtypes.xml.in
@@ -683,6 +683,23 @@
<input type="regex" name="expression"/>
</part>
+ <part name="addressbook">
+ <_title>Address book</_title>
+ <input type="optionlist" name="book">
+ <dynamic func="e_mail_addressbook_get_filter_options"/>
+ </input>
+ <input type="optionlist" name="compare-type">
+ <option value="contains-sender">
+ <_title>contains Sender</_title>
+ <code>(addressbook-contains ${book} "From")</code>
+ </option>
+ <option value="not-contains-sender">
+ <_title>does not contain Sender</_title>
+ <code>(not (addressbook-contains ${book} "From"))</code>
+ </option>
+ </input>
+ </part>
+
<part name="all">
<_title>Match All</_title>
<code>#t</code>
diff --git a/src/mail/vfoldertypes.xml.in b/src/mail/vfoldertypes.xml.in
index 90066c6497..92080e6f40 100644
--- a/src/mail/vfoldertypes.xml.in
+++ b/src/mail/vfoldertypes.xml.in
@@ -701,6 +701,23 @@
<input type="folder-curi" name="folder"/>
</part>
+ <part name="addressbook">
+ <_title>Address book</_title>
+ <input type="optionlist" name="book">
+ <dynamic func="e_mail_addressbook_get_filter_options"/>
+ </input>
+ <input type="optionlist" name="compare-type">
+ <option value="contains-sender">
+ <_title>contains Sender</_title>
+ <code>(addressbook-contains ${book} "From")</code>
+ </option>
+ <option value="not-contains-sender">
+ <_title>does not contain Sender</_title>
+ <code>(not (addressbook-contains ${book} "From"))</code>
+ </option>
+ </input>
+ </part>
+
<part name="all">
<_title>Match All</_title>
<code>#t</code>
diff --git a/src/modules/mail/e-mail-shell-backend.c b/src/modules/mail/e-mail-shell-backend.c
index bcff4d04d6..8186ed509d 100644
--- a/src/modules/mail/e-mail-shell-backend.c
+++ b/src/modules/mail/e-mail-shell-backend.c
@@ -1666,3 +1666,53 @@ e_mail_labels_get_filter_code (EFilterElement *element,
g_string_append (out, " ))");
}
+static gint
+filter_opts_sort_by_title_cb (gconstpointer aa,
+ gconstpointer bb)
+{
+ const struct _filter_option *opt_a = aa;
+ const struct _filter_option *opt_b = bb;
+
+ return g_utf8_collate (opt_a->title, opt_b->title);
+}
+
+GSList *
+e_mail_addressbook_get_filter_options (void)
+{
+ EShell *shell;
+ ESourceRegistry *registry;
+ GSList *list = NULL;
+ GList *sources, *link;
+ struct _filter_option *option;
+
+ shell = e_shell_get_default ();
+ registry = e_shell_get_registry (shell);
+ sources = e_source_registry_list_enabled (registry, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+
+ for (link = sources; link; link = g_list_next (link)) {
+ ESource *source = link->data;
+
+ option = g_new0 (struct _filter_option, 1);
+ option->title = e_util_get_source_full_name (registry, source);
+ option->value = e_source_dup_uid (source);
+ list = g_slist_prepend (list, option);
+ }
+
+ g_list_free_full (sources, g_object_unref);
+
+ list = g_slist_sort (list, filter_opts_sort_by_title_cb);
+
+ option = g_new0 (struct _filter_option, 1);
+ /* Translators: Meaning "any configured addressbook included in autocompletion" in the filter dialog
*/
+ option->title = g_strdup (C_("addrbook", "Included in Autocompletion"));
+ option->value = g_strdup (CAMEL_SESSION_BOOK_UID_COMPLETION);
+ list = g_slist_prepend (list, option);
+
+ option = g_new0 (struct _filter_option, 1);
+ /* Translators: Meaning "any configured addressbook" in the filter dialog */
+ option->title = g_strdup (C_("addrbook", "Any"));
+ option->value = g_strdup (CAMEL_SESSION_BOOK_UID_ANY);
+ list = g_slist_prepend (list, option);
+
+ return list;
+}
diff --git a/src/modules/mail/e-mail-shell-backend.h b/src/modules/mail/e-mail-shell-backend.h
index 79e0694beb..d5e5fb45cf 100644
--- a/src/modules/mail/e-mail-shell-backend.h
+++ b/src/modules/mail/e-mail-shell-backend.h
@@ -85,6 +85,8 @@ GSList * e_mail_labels_get_filter_options_without_none
void e_mail_labels_get_filter_code (EFilterElement *element,
GString *out,
EFilterPart *part);
+GSList * e_mail_addressbook_get_filter_options
+ (void);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]