[evolution-ews/wip/mcrha/office365: 30/50] Implement mail message send (CamelO365Transport)




commit 0997e4bb4077d1d8f0eadbf0c692132f20c5c6ae
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jul 8 11:44:56 2020 +0200

    Implement mail message send (CamelO365Transport)

 src/Office365/camel/camel-o365-folder.c    |   2 +-
 src/Office365/camel/camel-o365-transport.c | 278 +++++++++++++++++++++++++----
 src/Office365/camel/camel-o365-utils.c     | 172 ++++++++++++++----
 src/Office365/camel/camel-o365-utils.h     |  13 +-
 src/Office365/common/e-o365-connection.c   |  79 ++++++++
 src/Office365/common/e-o365-connection.h   |  12 ++
 6 files changed, 485 insertions(+), 71 deletions(-)
---
diff --git a/src/Office365/camel/camel-o365-folder.c b/src/Office365/camel/camel-o365-folder.c
index e085ebb6..b0c89027 100644
--- a/src/Office365/camel/camel-o365-folder.c
+++ b/src/Office365/camel/camel-o365-folder.c
@@ -628,7 +628,7 @@ o365_folder_append_message_sync (CamelFolder *folder,
                return FALSE;
 
        success = camel_o365_utils_create_message_sync (cnc, camel_o365_folder_get_id (CAMEL_O365_FOLDER 
(folder)),
-               message, info, FALSE, appended_uid, cancellable, &local_error);
+               message, info, appended_uid, cancellable, &local_error);
 
        g_clear_object (&cnc);
 
diff --git a/src/Office365/camel/camel-o365-transport.c b/src/Office365/camel/camel-o365-transport.c
index 27bbfe91..985a4efa 100644
--- a/src/Office365/camel/camel-o365-transport.c
+++ b/src/Office365/camel/camel-o365-transport.c
@@ -21,42 +21,143 @@
 
 #include <glib/gi18n-lib.h>
 
+#include <libemail-engine/libemail-engine.h>
+
 #include "common/camel-o365-settings.h"
+#include "common/e-o365-connection.h"
+#include "camel-o365-store.h"
+#include "camel-o365-utils.h"
 
 #include "camel-o365-transport.h"
 
+#define LOCK(_transport) g_mutex_lock (&_transport->priv->property_lock)
+#define UNLOCK(_transport) g_mutex_unlock (&_transport->priv->property_lock)
+
 struct _CamelO365TransportPrivate
 {
        GMutex property_lock;
-       /*EO365Connection *connection;*/
+       EO365Connection *cnc;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (CamelO365Transport, camel_o365_transport, CAMEL_TYPE_TRANSPORT)
 
-/*static EO365Connection *
+static gboolean
+o365_transport_is_server_side_sent_folder (CamelService *service,
+                                          GCancellable *cancellable)
+{
+       CamelSession *session;
+       ESourceRegistry *registry;
+       ESource *sibling, *source = NULL;
+       gboolean is_server_side = FALSE;
+
+       g_return_val_if_fail (CAMEL_IS_O365_TRANSPORT (service), FALSE);
+
+       session = camel_service_ref_session (service);
+
+       if (session && E_IS_MAIL_SESSION (session))
+               registry = g_object_ref (e_mail_session_get_registry (E_MAIL_SESSION (session)));
+       else
+               registry = e_source_registry_new_sync (cancellable, NULL);
+
+       if (!registry) {
+               g_clear_object (&session);
+               return FALSE;
+       }
+
+       sibling = e_source_registry_ref_source (registry, camel_service_get_uid (service));
+
+       if (sibling) {
+               GList *sources, *siter;
+
+               sources = e_source_registry_list_sources (registry, E_SOURCE_EXTENSION_MAIL_SUBMISSION);
+
+               for (siter = sources; siter; siter = siter->next) {
+                       source = siter->data;
+
+                       if (!source || g_strcmp0 (e_source_get_parent (source), e_source_get_parent 
(sibling)) != 0 ||
+                           !e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_SUBMISSION) ||
+                           !e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION))
+                               source = NULL;
+                       else
+                               break;
+               }
+
+               if (source &&
+                   e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_SUBMISSION) &&
+                   e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION)) {
+                       ESourceMailSubmission *subm_extension;
+                       CamelStore *store = NULL;
+                       gchar *folder_name = NULL;
+
+                       subm_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_SUBMISSION);
+
+                       /* Copy messages on the server side only if the replies
+                          might not be saved to the original folder, which is handled
+                          by the evolution itself. */
+                       if (!e_source_mail_submission_get_replies_to_origin_folder (subm_extension) &&
+                           e_source_mail_submission_get_sent_folder (subm_extension) &&
+                           e_mail_folder_uri_parse (session,
+                               e_source_mail_submission_get_sent_folder (subm_extension),
+                               &store, &folder_name, NULL) && CAMEL_IS_O365_STORE (store)) {
+                               CamelO365Store *o365_store = CAMEL_O365_STORE (store);
+                               CamelO365StoreSummary *o365_store_summary;
+                               gchar *folder_id_str;
+
+                               o365_store_summary = camel_o365_store_ref_store_summary (o365_store);
+                               folder_id_str = camel_o365_store_summary_dup_folder_id_for_full_name 
(o365_store_summary, folder_name);
+                               if (folder_id_str && *folder_id_str) {
+                                       guint32 flags;
+
+                                       flags = camel_o365_store_summary_get_folder_flags 
(o365_store_summary, folder_id_str);
+
+                                       if ((flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_SENT) {
+                                               is_server_side = TRUE;
+                                       }
+                               }
+
+                               g_clear_object (&o365_store_summary);
+                               g_free (folder_id_str);
+                       }
+
+                       g_clear_object (&store);
+                       g_free (folder_name);
+               }
+
+               g_list_free_full (sources, g_object_unref);
+               g_object_unref (sibling);
+       }
+
+       g_object_unref (registry);
+       g_clear_object (&session);
+
+       return is_server_side;
+}
+
+static EO365Connection *
 o365_transport_ref_connection (CamelO365Transport *o365_transport)
 {
-       EO365Connection *connection = NULL;
+       EO365Connection *cnc = NULL;
 
        g_return_val_if_fail (CAMEL_IS_O365_TRANSPORT (o365_transport), NULL);
 
-       g_mutex_lock (&o365_transport->priv->property_lock);
+       LOCK (o365_transport);
 
-       if (o365_transport->priv->connection)
-               connection = g_object_ref (o365_transport->priv->connection);
+       if (o365_transport->priv->cnc)
+               cnc = g_object_ref (o365_transport->priv->cnc);
 
-       g_mutex_unlock (&o365_transport->priv->property_lock);
+       UNLOCK (o365_transport);
 
-       return connection;
-}*/
+       return cnc;
+}
 
 static gboolean
 o365_transport_connect_sync (CamelService *service,
                             GCancellable *cancellable,
                             GError **error)
 {
-       CamelSession *session;
-       gboolean success;
+       CamelO365Transport *o365_transport;
+       EO365Connection *cnc;
+       gboolean success = FALSE;
 
        /* Chain up to parent's method. */
        if (!CAMEL_SERVICE_CLASS (camel_o365_transport_parent_class)->connect_sync (service, cancellable, 
error))
@@ -65,17 +166,29 @@ o365_transport_connect_sync (CamelService *service,
        if (camel_service_get_connection_status (service) == CAMEL_SERVICE_DISCONNECTED)
                return FALSE;
 
-       /*connection = o365_transport_ref_connection (CAMEL_O365_TRANSPORT (service));
-       if (connection) {
-               g_object_unref (connection);
-               return TRUE;
-       }*/
+       o365_transport = CAMEL_O365_TRANSPORT (service);
+       cnc = o365_transport_ref_connection (o365_transport);
 
-       session = camel_service_ref_session (service);
+       if (!cnc) {
+               LOCK (o365_transport);
+
+               o365_transport->priv->cnc = camel_o365_utils_new_connection (service, NULL);
+
+               UNLOCK (o365_transport);
+       }
 
-       success = camel_session_authenticate_sync (session, service, "Office365", cancellable, error);
+       if (cnc) {
+               CamelSession *session;
 
-       g_object_unref (session);
+               session = camel_service_ref_session (service);
+
+               success = camel_session_authenticate_sync (session, service, "Office365", cancellable, error);
+
+               g_clear_object (&session);
+               g_clear_object (&cnc);
+       } else {
+               g_set_error_literal (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("Failed 
to create connection"));
+       }
 
        return success;
 }
@@ -87,11 +200,21 @@ o365_transport_disconnect_sync (CamelService *service,
                                GError **error)
 {
        CamelO365Transport *o365_transport = CAMEL_O365_TRANSPORT (service);
+       EO365Connection *cnc;
+       gboolean success = TRUE;
+
+       cnc = o365_transport_ref_connection (o365_transport);
 
-       g_mutex_lock (&o365_transport->priv->property_lock);
-       /*g_clear_object (&o365_transport->priv->connection);*/
-       g_mutex_unlock (&o365_transport->priv->property_lock);
+       if (cnc) {
+               success = e_o365_connection_disconnect_sync (cnc, cancellable, error);
+
+               g_clear_object (&cnc);
+       }
+
+       if (!success)
+               return FALSE;
 
+       /* Chain up to parent's method. */
        return CAMEL_SERVICE_CLASS (camel_o365_transport_parent_class)->disconnect_sync (service, clean, 
cancellable, error);
 }
 
@@ -102,8 +225,31 @@ o365_transport_authenticate_sync (CamelService *service,
                                  GError **error)
 {
        CamelAuthenticationResult result;
-
-       result = CAMEL_AUTHENTICATION_ERROR;
+       CamelO365Transport *o365_transport;
+       EO365Connection *cnc;
+
+       o365_transport = CAMEL_O365_TRANSPORT (service);
+       cnc = o365_transport_ref_connection (o365_transport);
+
+       if (!cnc)
+               return CAMEL_AUTHENTICATION_ERROR;
+
+       switch (e_o365_connection_authenticate_sync (cnc, cancellable, error)) {
+       case E_SOURCE_AUTHENTICATION_ERROR:
+       case E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED:
+       default:
+               result = CAMEL_AUTHENTICATION_ERROR;
+               break;
+       case E_SOURCE_AUTHENTICATION_ACCEPTED:
+               result = CAMEL_AUTHENTICATION_ACCEPTED;
+               break;
+       case E_SOURCE_AUTHENTICATION_REJECTED:
+       case E_SOURCE_AUTHENTICATION_REQUIRED:
+               result = CAMEL_AUTHENTICATION_REJECTED;
+               break;
+       }
+
+       g_clear_object (&cnc);
 
        return result;
 }
@@ -115,9 +261,9 @@ o365_transport_get_name (CamelService *service,
        gchar *name;
 
        if (brief)
-               name = g_strdup (_("Office365 server"));
+               name = g_strdup (_("Office 365 server"));
        else
-               name = g_strdup (_("Mail delivery via Microsoft Office365"));
+               name = g_strdup (_("Mail delivery via Microsoft Office 365"));
 
        return name;
 }
@@ -131,7 +277,77 @@ o365_send_to_sync (CamelTransport *transport,
                   GCancellable *cancellable,
                   GError **error)
 {
-       return FALSE;
+       CamelInternetAddress *use_from;
+       CamelService *service;
+       EO365Connection *cnc;
+       JsonBuilder *builder;
+       gchar *appended_id = NULL;
+       gboolean is_server_side_sent;
+       gboolean success = FALSE;
+
+       service = CAMEL_SERVICE (transport);
+
+       if (CAMEL_IS_INTERNET_ADDRESS (from))
+               use_from = CAMEL_INTERNET_ADDRESS (from);
+       else
+               use_from = camel_mime_message_get_from (message);
+
+       if (!use_from || camel_address_length (CAMEL_ADDRESS (use_from)) == 0) {
+               g_set_error_literal (
+                       error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+                       _("Cannot send message with no From address"));
+               return FALSE;
+
+       } else if (camel_address_length (CAMEL_ADDRESS (use_from)) > 1) {
+               g_set_error_literal (
+                       error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+                       _("Office 365 server cannot send message with multiple From addresses"));
+               return FALSE;
+
+       } else {
+               const gchar *used_email = NULL;
+
+               if (!camel_internet_address_get (use_from, 0, NULL, &used_email)) {
+                       g_set_error_literal (
+                               error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+                               _("Failed to read From address"));
+                       return FALSE;
+               }
+       }
+
+       cnc = o365_transport_ref_connection (CAMEL_O365_TRANSPORT (service));
+
+       if (!cnc) {
+               g_set_error_literal (
+                       error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_NOT_CONNECTED,
+                       _("Service not connected"));
+               return FALSE;
+       }
+
+       is_server_side_sent = o365_transport_is_server_side_sent_folder (service, cancellable);
+
+       if (is_server_side_sent && out_sent_message_saved)
+               *out_sent_message_saved = TRUE;
+
+       builder = json_builder_new_immutable ();
+       e_o365_json_begin_object_member (builder, NULL);
+       e_o365_json_begin_object_member (builder, "message");
+
+       success = camel_o365_utils_fill_message_object_sync (builder, message, NULL, from, recipients, TRUE, 
NULL, cancellable, error);
+
+       e_o365_json_end_object_member (builder); /* message */
+
+       if (!is_server_side_sent)
+               e_o365_json_add_boolean_member (builder, "saveToSentItems", FALSE);
+
+       e_o365_json_end_object_member (builder);
+
+       success = success && e_o365_connection_send_mail_sync (cnc, NULL, builder, cancellable, error);
+
+       g_object_unref (cnc);
+       g_free (appended_id);
+
+       return success;
 }
 
 static void
@@ -139,9 +355,11 @@ o365_transport_dispose (GObject *object)
 {
        CamelO365Transport *o365_transport = CAMEL_O365_TRANSPORT (object);
 
-       g_mutex_lock (&o365_transport->priv->property_lock);
-       /*g_clear_object (&o365_transport->priv->connection);*/
-       g_mutex_unlock (&o365_transport->priv->property_lock);
+       LOCK (o365_transport);
+
+       g_clear_object (&o365_transport->priv->cnc);
+
+       UNLOCK (o365_transport);
 
        /* Chain up to parent's method. */
        G_OBJECT_CLASS (camel_o365_transport_parent_class)->dispose (object);
diff --git a/src/Office365/camel/camel-o365-utils.c b/src/Office365/camel/camel-o365-utils.c
index 20f51181..3d24749b 100644
--- a/src/Office365/camel/camel-o365-utils.c
+++ b/src/Office365/camel/camel-o365-utils.c
@@ -209,7 +209,9 @@ static void
 o365_utils_add_address_array (JsonBuilder *builder,
                              CamelInternetAddress *addr,
                              void (* begin_func) (JsonBuilder *builder),
-                             void (* end_func) (JsonBuilder *builder))
+                             void (* end_func) (JsonBuilder *builder),
+                             GHashTable *known_recipients,
+                             CamelAddress *expected_recipients)
 {
        gint ii, len;
        gboolean did_add = FALSE;
@@ -231,10 +233,36 @@ o365_utils_add_address_array (JsonBuilder *builder,
                                begin_func (builder);
                        }
 
+                       if (known_recipients && address && *address)
+                               g_hash_table_add (known_recipients, (gpointer) address);
+
                        e_o365_add_recipient (builder, NULL, name, address);
                }
        }
 
+       if (known_recipients && expected_recipients && CAMEL_IS_INTERNET_ADDRESS (expected_recipients)) {
+               CamelInternetAddress *iaddr = CAMEL_INTERNET_ADDRESS (expected_recipients);
+
+               len = camel_address_length (expected_recipients);
+
+               for (ii = 0; ii < len; ii++) {
+                       const gchar *name = NULL, *address = NULL;
+
+                       if (camel_internet_address_get (iaddr, 0, &name, &address) && address && *address &&
+                           !g_hash_table_contains (known_recipients, address)) {
+                               if (!did_add) {
+                                       did_add = TRUE;
+                                       begin_func (builder);
+                               }
+
+                               if (known_recipients && address && *address)
+                                       g_hash_table_add (known_recipients, (gpointer) address);
+
+                               e_o365_add_recipient (builder, NULL, name, address);
+                       }
+               }
+       }
+
        if (did_add)
                end_func (builder);
 }
@@ -740,33 +768,52 @@ camel_o365_utils_add_message_flags (JsonBuilder *builder,
        e_o365_mail_message_add_is_read (builder, (flags & CAMEL_MESSAGE_SEEN) != 0);
 }
 
+static void
+o365_utils_add_attachment_object (JsonBuilder *builder,
+                                 CamelDataWrapper *dw,
+                                 GCancellable *cancellable)
+{
+       CamelContentType *ct;
+
+       ct = camel_data_wrapper_get_mime_type_field (dw);
+
+       e_o365_attachment_begin_attachment (builder, E_O365_ATTACHMENT_DATA_TYPE_FILE);
+
+       if (camel_content_type_is (ct, "application", "x-pkcs7-mime") ||
+           camel_content_type_is (ct, "application", "pkcs7-mime")) {
+               o365_utils_add_smime_encrypted_attachment (builder, dw, cancellable);
+       } else if (CAMEL_IS_MULTIPART_SIGNED (dw)) {
+               o365_utils_add_smime_signed_attachment (builder, dw, cancellable);
+       } else {
+               o365_utils_add_file_attachment (builder, dw, cancellable);
+       }
+
+       e_o365_json_end_object_member (builder);
+}
+
 gboolean
-camel_o365_utils_create_message_sync (EO365Connection *cnc,
-                                     const gchar *folder_id,
-                                     CamelMimeMessage *message,
-                                     CamelMessageInfo *info,
-                                     gboolean is_send,
-                                     gchar **out_appended_uid,
-                                     GCancellable *cancellable,
-                                     GError **error)
+camel_o365_utils_fill_message_object_sync (JsonBuilder *builder,
+                                          CamelMimeMessage *message,
+                                          CamelMessageInfo *info,
+                                          CamelAddress *override_from,
+                                          CamelAddress *override_recipients, /* it merges them, not really 
override */
+                                          gboolean is_send,
+                                          GSList **out_attachments,
+                                          GCancellable *cancellable,
+                                          GError **error)
 {
-       JsonBuilder *builder;
-       EO365MailMessage *appended_message = NULL;
        CamelInternetAddress *addr, *sender = NULL;
        CamelMimePart *body_part;
+       GHashTable *known_recipients = NULL;
        GSList *attachments = NULL;
        time_t tt;
        gint offset = 0;
        const gchar *tmp;
-       gboolean success, request_read_receipt = FALSE;
+       gboolean success = TRUE, request_read_receipt = FALSE;
 
-       g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
+       g_return_val_if_fail (builder != NULL, FALSE);
        g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
 
-       builder = json_builder_new_immutable ();
-
-       e_o365_json_begin_object_member (builder, NULL);
-
        tmp = camel_mime_message_get_message_id (message);
        if (tmp && *tmp)
                e_o365_mail_message_add_internet_message_id (builder, tmp);
@@ -795,20 +842,31 @@ camel_o365_utils_create_message_sync (EO365Connection *cnc,
                e_o365_mail_message_add_received_date_time (builder, tt);
        }
 
-       addr = camel_mime_message_get_from (message);
+       if (override_recipients)
+               known_recipients = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
+
+       if (override_from && CAMEL_IS_INTERNET_ADDRESS (override_from))
+               addr = CAMEL_INTERNET_ADDRESS (override_from);
+       else
+               addr = camel_mime_message_get_from (message);
        o365_utils_add_address (builder, addr, e_o365_mail_message_add_from);
 
        addr = camel_mime_message_get_reply_to (message);
-       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_reply_to, 
e_o365_mail_message_end_reply_to);
+       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_reply_to, 
e_o365_mail_message_end_reply_to, NULL, NULL);
 
        addr = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
-       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_to_recipients, 
e_o365_mail_message_end_to_recipients);
+       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_to_recipients, 
e_o365_mail_message_end_to_recipients, known_recipients, NULL);
 
        addr = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
-       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_cc_recipients, 
e_o365_mail_message_end_cc_recipients);
+       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_cc_recipients, 
e_o365_mail_message_end_cc_recipients, known_recipients, NULL);
 
        addr = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
-       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_bcc_recipients, 
e_o365_mail_message_end_bcc_recipients);
+       o365_utils_add_address_array (builder, addr, e_o365_mail_message_begin_bcc_recipients, 
e_o365_mail_message_end_bcc_recipients, known_recipients, override_recipients);
+
+       if (known_recipients) {
+               g_hash_table_destroy (known_recipients);
+               known_recipients = NULL;
+       }
 
        o365_utils_add_headers (builder, camel_medium_get_headers (CAMEL_MEDIUM (message)), &sender, 
&request_read_receipt);
 
@@ -819,6 +877,8 @@ camel_o365_utils_create_message_sync (EO365Connection *cnc,
                        e_o365_mail_message_add_sender (builder, name, address);
 
                g_clear_object (&sender);
+       } else if (override_from) {
+               /* Possibly force the Sender when the passed-in From doesn't match the account user address */
        }
 
        if (request_read_receipt)
@@ -867,6 +927,55 @@ camel_o365_utils_create_message_sync (EO365Connection *cnc,
        if (info || is_send)
                camel_o365_utils_add_message_flags (builder, info, is_send ? message : NULL);
 
+       if (out_attachments) {
+               *out_attachments = attachments;
+       } else if (attachments) {
+               GSList *link;
+
+               e_o365_json_begin_array_member (builder, "attachments");
+
+               for (link = attachments; link && success; link = g_slist_next (link)) {
+                       CamelDataWrapper *dw = link->data;
+
+                       o365_utils_add_attachment_object (builder, dw, cancellable);
+               }
+
+               e_o365_json_end_array_member (builder);
+
+               g_slist_free_full (attachments, g_object_unref);
+       }
+
+       return success;
+}
+
+gboolean
+camel_o365_utils_create_message_sync (EO365Connection *cnc,
+                                     const gchar *folder_id,
+                                     CamelMimeMessage *message,
+                                     CamelMessageInfo *info,
+                                     gchar **out_appended_id,
+                                     GCancellable *cancellable,
+                                     GError **error)
+{
+       EO365MailMessage *appended_message = NULL;
+       GSList *attachments = NULL;
+       JsonBuilder *builder;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
+       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
+
+       builder = json_builder_new_immutable ();
+
+       e_o365_json_begin_object_member (builder, NULL);
+
+       if (!camel_o365_utils_fill_message_object_sync (builder, message, info, NULL, NULL, FALSE, 
&attachments, cancellable, error)) {
+               g_slist_free_full (attachments, g_object_unref);
+               g_object_unref (builder);
+
+               return FALSE;
+       }
+
        e_o365_json_end_object_member (builder);
 
        success = e_o365_connection_create_mail_message_sync (cnc, NULL, folder_id, builder, 
&appended_message, cancellable, error);
@@ -881,28 +990,15 @@ camel_o365_utils_create_message_sync (EO365Connection *cnc,
 
                message_id = e_o365_mail_message_get_id (appended_message);
 
-               if (out_appended_uid)
-                       *out_appended_uid = g_strdup (message_id);
+               if (out_appended_id)
+                       *out_appended_id = g_strdup (message_id);
 
                for (link = attachments; link && success; link = g_slist_next (link)) {
                        CamelDataWrapper *dw = link->data;
-                       CamelContentType *ct;
-
-                       ct = camel_data_wrapper_get_mime_type_field (dw);
 
                        builder = json_builder_new_immutable ();
-                       e_o365_attachment_begin_attachment (builder, E_O365_ATTACHMENT_DATA_TYPE_FILE);
-
-                       if (camel_content_type_is (ct, "application", "x-pkcs7-mime") ||
-                           camel_content_type_is (ct, "application", "pkcs7-mime")) {
-                               o365_utils_add_smime_encrypted_attachment (builder, dw, cancellable);
-                       } else if (CAMEL_IS_MULTIPART_SIGNED (dw)) {
-                               o365_utils_add_smime_signed_attachment (builder, dw, cancellable);
-                       } else {
-                               o365_utils_add_file_attachment (builder, dw, cancellable);
-                       }
 
-                       e_o365_json_end_object_member (builder);
+                       o365_utils_add_attachment_object (builder, dw, cancellable);
 
                        success = e_o365_connection_add_mail_message_attachment_sync (cnc, NULL, message_id, 
builder, NULL, cancellable, error);
 
diff --git a/src/Office365/camel/camel-o365-utils.h b/src/Office365/camel/camel-o365-utils.h
index 3815c322..1cd109cd 100644
--- a/src/Office365/camel/camel-o365-utils.h
+++ b/src/Office365/camel/camel-o365-utils.h
@@ -37,13 +37,22 @@ void                camel_o365_utils_add_message_flags
                                                (JsonBuilder *builder,
                                                 CamelMessageInfo *info,
                                                 CamelMimeMessage *message);
+gboolean       camel_o365_utils_fill_message_object_sync
+                                               (JsonBuilder *builder,
+                                                CamelMimeMessage *message,
+                                                CamelMessageInfo *info,
+                                                CamelAddress *override_from,
+                                                CamelAddress *override_recipients, /* it merges them, not 
really override */
+                                                gboolean is_send,
+                                                GSList **out_attachments,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gboolean       camel_o365_utils_create_message_sync
                                                (EO365Connection *cnc,
                                                 const gchar *folder_id,
                                                 CamelMimeMessage *message,
                                                 CamelMessageInfo *info,
-                                                gboolean is_send,
-                                                gchar **out_appended_uid,
+                                                gchar **out_appended_id,
                                                 GCancellable *cancellable,
                                                 GError **error);
 
diff --git a/src/Office365/common/e-o365-connection.c b/src/Office365/common/e-o365-connection.c
index 9ceb2486..91e81161 100644
--- a/src/Office365/common/e-o365-connection.c
+++ b/src/Office365/common/e-o365-connection.c
@@ -3032,3 +3032,82 @@ e_o365_connection_delete_mail_messages_sync (EO365Connection *cnc,
 
        return success;
 }
+
+/* https://docs.microsoft.com/en-us/graph/api/message-send?view=graph-rest-1.0&tabs=http */
+
+gboolean
+e_o365_connection_send_mail_message_sync (EO365Connection *cnc,
+                                    const gchar *user_override, /* for which user, NULL to use the account 
user */
+                                    const gchar *message_id,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       SoupMessage *message;
+       gboolean success;
+       gchar *uri;
+
+       g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
+       g_return_val_if_fail (message_id != NULL, FALSE);
+
+       uri = e_o365_connection_construct_uri (cnc, TRUE, user_override, E_O365_API_V1_0, NULL,
+               "messages",
+               message_id,
+               "send",
+               NULL);
+
+       message = o365_connection_new_soup_message (SOUP_METHOD_POST, uri, CSM_DEFAULT, error);
+
+       if (!message) {
+               g_free (uri);
+
+               return FALSE;
+       }
+
+       g_free (uri);
+
+       soup_message_headers_append (message->request_headers, "Content-Length", "0");
+
+       success = o365_connection_send_request_sync (cnc, message, NULL, e_o365_read_no_response_cb, NULL, 
cancellable, error);
+
+       g_clear_object (&message);
+
+       return success;
+}
+
+/* https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http */
+
+gboolean
+e_o365_connection_send_mail_sync (EO365Connection *cnc,
+                                 const gchar *user_override, /* for which user, NULL to use the account user 
*/
+                                 JsonBuilder *request, /* filled sendMail object */
+                                 GCancellable *cancellable,
+                                 GError **error)
+{
+       SoupMessage *message;
+       gboolean success;
+       gchar *uri;
+
+       g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
+       g_return_val_if_fail (request != NULL, FALSE);
+
+       uri = e_o365_connection_construct_uri (cnc, TRUE, user_override, E_O365_API_V1_0, NULL,
+               "sendMail", NULL, NULL, NULL);
+
+       message = o365_connection_new_soup_message (SOUP_METHOD_POST, uri, CSM_DEFAULT, error);
+
+       if (!message) {
+               g_free (uri);
+
+               return FALSE;
+       }
+
+       g_free (uri);
+
+       e_o365_connection_set_json_body (message, request);
+
+       success = o365_connection_send_request_sync (cnc, message, NULL, e_o365_read_no_response_cb, NULL, 
cancellable, error);
+
+       g_clear_object (&message);
+
+       return success;
+}
diff --git a/src/Office365/common/e-o365-connection.h b/src/Office365/common/e-o365-connection.h
index f8af1cfd..5174641f 100644
--- a/src/Office365/common/e-o365-connection.h
+++ b/src/Office365/common/e-o365-connection.h
@@ -281,6 +281,18 @@ gboolean   e_o365_connection_delete_mail_messages_sync
                                                 GSList **out_deleted_ids, /* (transfer container): const 
gchar *, borrowed from message_ids */
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_o365_connection_send_mail_message_sync
+                                               (EO365Connection *cnc,
+                                                const gchar *user_override, /* for which user, NULL to use 
the account user */
+                                                const gchar *message_id,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_o365_connection_send_mail_sync
+                                               (EO365Connection *cnc,
+                                                const gchar *user_override, /* for which user, NULL to use 
the account user */
+                                                JsonBuilder *request, /* filled sendMail object */
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]