static CamelMimePart *
multipart_remove_part_at (CamelMultipart *multipart,
                          guint index)
{
	CamelMimePart *removed_part;
	GList *link;

	if (!(multipart->parts))
		return NULL;

	link = g_list_nth (multipart->parts, index);
	if (link == NULL) {
		g_warning ("CamelMultipart::remove_part_at: "
			   "part to remove is NULL\n");
		return NULL;
	}
	removed_part = CAMEL_MIME_PART (link->data);

	multipart->parts = g_list_remove_link (multipart->parts, link);
	if (link->data)
		g_object_unref (link->data);
	g_list_free_1 (link);

	return removed_part;
}
Esempio n. 2
0
static gchar *
get_full_header (CamelMimeMessage *message)
{
	CamelMimePart *mime_part;
	GString *str = g_string_new ("");
	gchar   *ret;
	struct _camel_header_raw *h;

	mime_part = CAMEL_MIME_PART (message);

	for (h = mime_part->headers; h; h = h->next) {
		if (h->value != NULL) {
			g_string_append (str, h->name);
			if (isspace (h->value[0]))
				g_string_append (str, ":");
			else
				g_string_append (str, ": ");
			g_string_append (str, h->value);
			g_string_append_c (str, '\n');
		}
	}

	ret = str->str;
	g_string_free (str, FALSE);

	return ret;
}
Esempio n. 3
0
/**
 *
 * "util_get_msg_body" is based on mail-to-task eplugin's get_description function.
 * which is GPL licensed.
 * */
static gchar *
util_get_msg_body(CamelMimeMessage *message, gchar **text) {
   CamelDataWrapper *content;
   CamelStream *mem;
   CamelContentType *type;
   CamelMimePart *mime_part = CAMEL_MIME_PART(message);

   GSList sl;
   gchar *str, *convert_str = NULL;
   gsize bytes_read, bytes_written;
   gint count = 2;

   content = camel_medium_get_content_object((CamelMedium *) message);

   if (!content)
      return;

   /*
    * Get non-multipart content from multipart message.
    */
   while (CAMEL_IS_MULTIPART(content) && count > 0) {
      mime_part = camel_multipart_get_part(CAMEL_MULTIPART(content), 0);
      content = camel_medium_get_content_object(CAMEL_MEDIUM(mime_part));
      count--;
   }

   if (!mime_part)
      return;

   type = camel_mime_part_get_content_type(mime_part);
   if (!camel_content_type_is(type, "text", "plain"))
      return;

   mem = camel_stream_mem_new();
   camel_data_wrapper_decode_to_stream(content, mem);

   str = g_strndup((const gchar *) ((CamelStreamMem *) mem)->buffer->data, ((CamelStreamMem *) mem)->buffer->len);
   camel_object_unref(mem);

   /* convert to UTF-8 string */
   if (str && content->mime_type->params && content->mime_type->params->value) {
      convert_str = g_convert(str, strlen(str),
            "UTF-8", content->mime_type->params->value,
            &bytes_read, &bytes_written, NULL);
   }

   if (convert_str)
      *text = convert_str;
   else
      *text = str;

   /*g_free (str);
     if (convert_str)
     g_free (convert_str);
     */
}
static TnyMsg *
tny_camel_partial_msg_receive_strategy_perform_get_msg_default (TnyMsgReceiveStrategy *self, TnyFolder *folder, TnyHeader *header, GError **err)
{
	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (folder);
	TnyMsg *message = NULL;
	CamelMimeMessage *camel_message = NULL;
	gchar *id;
	CamelException ex = CAMEL_EXCEPTION_INITIALISER;
	CamelFolderReceiveType mtype = CAMEL_FOLDER_RECEIVE_PARTIAL;

	g_assert (TNY_IS_HEADER (header));

	if (!priv->strict_retrieval)
		mtype = CAMEL_FOLDER_RECEIVE_ANY_OR_PARTIAL;

	id = tny_header_dup_uid (TNY_HEADER (header));

	message = NULL;
	camel_message = camel_folder_get_message (priv->folder, (const char *) id, mtype, -1, &ex);
	g_free (id);

	if (camel_exception_is_set (&ex))
	{
		_tny_camel_exception_to_tny_error (&ex, err);
		camel_exception_clear (&ex);
	} else 
	{
		if (camel_message && CAMEL_IS_OBJECT (camel_message))
		{
			TnyHeader *nheader = NULL;

			nheader = _tny_camel_msg_header_new (CAMEL_MIME_MESSAGE (camel_message), folder,
				tny_header_get_date_received (header));
			_tny_camel_msg_header_set_decorated (TNY_CAMEL_MSG_HEADER (nheader), header, FALSE);
			message = tny_camel_msg_new ();
			_tny_camel_msg_set_received (TNY_CAMEL_MSG (message), 
				tny_header_get_date_received (header));
			_tny_camel_msg_set_folder (TNY_CAMEL_MSG (message), folder);
			TNY_CAMEL_MSG_HEADER (nheader)->old_uid = tny_header_dup_uid (header);
			_tny_camel_msg_set_header (TNY_CAMEL_MSG (message), nheader);
			_tny_camel_mime_part_set_part (TNY_CAMEL_MIME_PART (message), 
						CAMEL_MIME_PART (camel_message)); 
			tny_header_set_flag (nheader, TNY_HEADER_FLAG_CACHED);
			tny_header_set_flag (nheader, TNY_HEADER_FLAG_PARTIAL);
			g_object_unref (nheader);
			tny_header_set_flag (header, TNY_HEADER_FLAG_CACHED);
			tny_header_set_flag (header, TNY_HEADER_FLAG_PARTIAL);
		}
	}

	if (camel_message && CAMEL_IS_OBJECT (camel_message))
		camel_object_unref (CAMEL_OBJECT (camel_message));

	return message;
}
static CamelMimePart *
multipart_get_part (CamelMultipart *multipart,
                    guint index)
{
	GList *part;

	if (!(multipart->parts))
		return NULL;

	part = g_list_nth (multipart->parts, index);
	if (part)
		return CAMEL_MIME_PART (part->data);
	else
		return NULL;
}
gboolean
mail_send_short_message (EGdbusSession *object,
		GDBusMethodInvocation *invocation, const char *account_uid,
		const char *text, const char **to,
		EMailDataSession *msession, GError **ret_error)
{
	EAccount *account;
	CamelMimeMessage *message;
	CamelService *service;
	gchar *transport_uid;
	CamelInternetAddress *recipients;
	CamelMessageInfo *info;
	GSimpleAsyncResult *simple;
	SendAsyncContext *context;
	CamelInternetAddress *from;
	GCancellable *ops;
	EMailDataOperation *mops;
	char *mops_path;
	gchar subject[MAX_SUBJECT_LENGTH + 4];
	GError *error = NULL;

	/* Check params. */

	if (account_uid == NULL || *account_uid == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Invalid account"));
		goto on_error;
	}
	if (text == NULL || *text == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Text is empty"));
		goto on_error;
	}
	if (to == NULL || *to == 0 || **to == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("No recipient"));
		goto on_error;
	}

	/* Get transport. */

	account = e_get_account_by_uid (account_uid);
	if (!account) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Invalid account %s"),
						account_uid);
		goto on_error;
	}

	transport_uid = g_strconcat (account->uid, "-transport", NULL);
	service = camel_session_ref_service (CAMEL_SESSION (session),
								transport_uid);
	if (!CAMEL_IS_TRANSPORT (service)) {
		error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
					_("Invalid account %s"), account_uid);
		g_object_unref (account);
		g_free (transport_uid);
		goto on_error;
	}

	/* Prepare message. */

	message = camel_mime_message_new ();
	strncpy (subject, text, MAX_SUBJECT_LENGTH + 1);
	if (strlen(text) > MAX_SUBJECT_LENGTH)
		strcpy (subject + MAX_SUBJECT_LENGTH, "...");
	camel_mime_message_set_subject (message, subject);
	from = camel_internet_address_new ();
	camel_internet_address_add (from, NULL, "sms");
	recipients = camel_internet_address_new ();
	while (*to) {
		camel_internet_address_add (recipients, NULL, *to);
		to++;
	}
	camel_mime_message_set_from (message, from);
	camel_mime_message_set_recipients (message, CAMEL_RECIPIENT_TYPE_TO,
								recipients);
	camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
	camel_mime_part_set_content_type (CAMEL_MIME_PART(message),
								"text/plain");
	camel_mime_part_set_content (CAMEL_MIME_PART(message), text,
						strlen(text), "text/plain");

	info = camel_message_info_new (NULL);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* Return the new operation */

	ops = camel_operation_new ();
	mops = e_mail_data_operation_new ((CamelOperation *) ops);

	mops_path = e_mail_data_operation_register_gdbus_object (mops,
			g_dbus_method_invocation_get_connection(invocation),
			NULL);
	egdbus_session_complete_send_short_message (object, invocation,
								mops_path);

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (SendAsyncContext);
	context->message = message;
	context->io_priority = G_PRIORITY_DEFAULT;
	context->from = CAMEL_ADDRESS (from);
	context->recipients = CAMEL_ADDRESS (recipients);
	context->info = info;
	context->transport = service;
	context->sent_folder_uri = g_strdup (account->sent_folder_uri);
	context->cancellable = ops;
	context->ops_path = mops_path;
	context->result = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
				CAMEL_SESSION (session), "outgoing", &error);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (context->cancellable,
							_("Sending message"));

	simple = g_simple_async_result_new (
			G_OBJECT (session), mail_send_short_message_completed,
			context, mail_send_short_message);

	g_simple_async_result_set_op_res_gpointer (
			simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
			simple,
			(GSimpleAsyncThreadFunc) mail_send_short_to_thread,
			context->io_priority, context->cancellable);

	g_object_unref (simple);

	return TRUE;

on_error:

	*ret_error = error;

	return FALSE;
}
CamelMimeMessage *
scalix_appointment_to_mime_message (ScalixObject * object)
{
    CamelMimeMessage *message;
    CamelMultipart *multipart;
    CamelMimePart *part;
    CamelMedium *medium;
    CamelStream *stream;
    CamelDataWrapper *wrapper;
    ECalComponentDateTime dtstart, dtend;
    ECalComponent *comp;
    ECalComponentText text;
    icalcomponent_kind kind;
    icalcomponent *icalcomp, *toplevel_comp;
    icaltimezone *zone = NULL;
    GSList *attachment_list = NULL;
    GSList *attachment_list_new = NULL;
    GSList *siter = NULL;
    GList *part_list = NULL;
    GList *iter = NULL;
    char *msgid;
    char *str, *meeting_status;
    const char *ouid = NULL;
    char *file_contents = NULL;
    char *full_path, *filename, *mime_filename;
    char *cid;
    int size;

    g_object_get (SCALIX_APPOINTMENT (object), "timezone", &zone, NULL);

    comp = E_CAL_COMPONENT (scalix_object_clone (object));
    message = camel_mime_message_new ();
    medium = CAMEL_MEDIUM (message);

    camel_medium_add_header (medium, "X-Scalix-Class", "IPM.Appointment");

    /* Preserve msg id if there is already one */
    if (scalix_appointment_get (SCALIX_APPOINTMENT (comp),
                                X_SCALIX_MSG_ID, &msgid)) {

        scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_MSG_ID);

    } else {
        msgid = camel_header_msgid_generate ();
    }

    camel_mime_message_set_message_id (message, msgid);

    /* subject */
    e_cal_component_get_summary (comp, &text);

    if (text.value != NULL) {
        camel_mime_message_set_subject (message, text.value);
    }

    /* start day */
    e_cal_component_get_dtstart (comp, &dtstart);

    if (!icaltime_get_timezone (*dtstart.value))
        icaltime_set_timezone (dtstart.value,
                               icaltimezone_get_builtin_timezone_from_tzid
                               (dtstart.tzid));

    /* end day */
    e_cal_component_get_dtend (comp, &dtend);

    if (!icaltime_get_timezone (*dtend.value))
        icaltime_set_timezone (dtend.value,
                               icaltimezone_get_builtin_timezone_from_tzid
                               (dtend.tzid));

    /* set From: and Sender: */
    if (e_cal_component_has_organizer (comp)) {
        ECalComponentOrganizer organizer;

        e_cal_component_get_organizer (comp, &organizer);
        if (!strncasecmp (organizer.value, "MAILTO:", 7)) {
            camel_medium_add_header (medium, "Sender", organizer.value + 7);
            camel_medium_add_header (medium, "From", organizer.value + 7);
        }
    }

    /* set the appropriate recipient headers from the recipient table */
    if (e_cal_component_has_attendees (comp)
        && e_cal_component_has_organizer (comp)) {
        GSList *iter, *attendees = NULL;
        CamelInternetAddress *recipients_to = NULL;
        CamelInternetAddress *recipients_cc = NULL;

        meeting_status = "1";

        e_cal_component_get_attendee_list (comp, &attendees);

        for (iter = attendees; iter; iter = iter->next) {
            ECalComponentAttendee *attendee = iter->data;
            const char *mail = NULL;

            /* attendee entries must start with MAILTO: */
            if (strncasecmp (attendee->value, "MAILTO:", 7)) {
                continue;
            }

            mail = attendee->value + 7;

            if (attendee->role == ICAL_ROLE_REQPARTICIPANT) {
                if (recipients_to == NULL) {
                    recipients_to = camel_internet_address_new ();
                }
                camel_internet_address_add (recipients_to, attendee->cn, mail);
            } else if (attendee->role == ICAL_ROLE_OPTPARTICIPANT) {
                if (recipients_cc == NULL) {
                    recipients_cc = camel_internet_address_new ();
                }
                camel_internet_address_add (recipients_cc, attendee->cn, mail);
            } else {
                continue;
            }
        }

        if (recipients_to != NULL) {
            camel_mime_message_set_recipients (message, "To", recipients_to);
            camel_object_unref (recipients_to);
        }

        if (recipients_cc != NULL) {
            camel_mime_message_set_recipients (message, "Cc", recipients_cc);
            camel_object_unref (recipients_cc);
        }
    } else {
        meeting_status = "0";
    }

    /* Clear properties */
    scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_IMAP_UID);
    /* Render the text/calendar  */
    e_cal_component_commit_sequence (comp);
    icalcomp = e_cal_component_get_icalcomponent (comp);

    kind = icalcomponent_isa (icalcomp);
    if (kind != ICAL_VCALENDAR_COMPONENT) {
        /* If its not a VCALENDAR, make it one to simplify below */
        toplevel_comp = e_cal_util_new_top_level ();
        icalcomponent_add_component (toplevel_comp, icalcomp);
        icalcomp = toplevel_comp;
    }

    /* set METHOD to PUSBLISH */
    icalcomponent_set_method (icalcomp, ICAL_METHOD_PUBLISH);

    /* Add the VTIMEZONE components for start- and/or end-times */
    if (zone) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component (zone));
    } else if (dtstart.tzid) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component
                                     (icaltimezone_get_builtin_timezone_from_tzid
                                      (dtstart.tzid)));
    }

    if (dtstart.tzid && dtend.tzid && strcmp (dtstart.tzid, dtend.tzid) != 0) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component
                                     (icaltimezone_get_builtin_timezone_from_tzid
                                      (dtend.tzid)));
    }

    /* FIXME: do we leek icalcomponents here? */

    if (e_cal_component_has_attachments (comp)) {

        multipart = camel_multipart_new ();
        camel_multipart_set_boundary (multipart, NULL);

        e_cal_component_get_uid (comp, &ouid);
        e_cal_component_get_attachment_list (comp, &attachment_list);

        for (siter = attachment_list; siter; siter = siter->next) {

            if (siter->data == NULL)
                continue;

            if (strstr (siter->data, "file://") != siter->data)
                continue;

            full_path = ((char *) siter->data) + strlen ("file://");
            filename = g_strrstr (full_path, "/") + 1;
            mime_filename = filename + strlen (ouid) + 1;

            size = 0;
            file_contents = get_file_contents (full_path, &size);

            if (file_contents == NULL)
                continue;

            stream = camel_stream_mem_new_with_buffer (file_contents, size);
            wrapper = camel_data_wrapper_new ();
            camel_data_wrapper_construct_from_stream (wrapper, stream);
            camel_object_unref (stream);

            part = camel_mime_part_new ();
            camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
            camel_mime_part_set_filename (part, mime_filename);
            camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);

            cid = camel_header_msgid_generate ();
            camel_mime_part_set_content_id (part, cid);
            camel_mime_part_set_description (part, mime_filename);
            camel_mime_part_set_disposition (part, "attachment");
            part_list = g_list_append (part_list, part);

            attachment_list_new = g_slist_append (attachment_list_new,
                                                  g_strdup_printf ("CID:%s",
                                                                   cid));
            g_free (cid);
        }

        e_cal_component_set_attachment_list (comp, attachment_list_new);
        str = icalcomponent_as_ical_string (icalcomp);

        part = camel_mime_part_new ();

        camel_mime_part_set_content (part,
                                     str,
                                     strlen (str),
                                     "text/calendar; method=PUBLISH; charset=UTF-8");

        part_list = g_list_prepend (part_list, part);

        for (iter = part_list; iter; iter = iter->next) {
            part = (CamelMimePart *) iter->data;
            camel_multipart_add_part (multipart, part);
            camel_object_unref (part);
        }

        camel_medium_set_content_object (CAMEL_MEDIUM (message),
                                         CAMEL_DATA_WRAPPER (multipart));
        camel_object_unref (multipart);

        g_slist_free (attachment_list);
        g_slist_free (attachment_list_new);
        g_list_free (part_list);

    } else {
        str = icalcomponent_as_ical_string (icalcomp);

        camel_mime_part_set_content (CAMEL_MIME_PART (message),
                                     str,
                                     strlen (str),
                                     "text/calendar; method=PUBLISH; charset=UTF-8");
    }

    scalix_appointment_set (SCALIX_APPOINTMENT (object),
                            X_SCALIX_MSG_ID, msgid);

    return message;
}
gboolean
scalix_appointment_init_from_mime_message (ScalixObject * object,
                                           CamelMimeMessage * msg)
{
    const char *msgid;
    const char *attachment_store;
    const char *mime_type, *alternative_mime_type;
    const char *content_disposition;
    const char *mime_filename;
    const char *cid;
    const char *cuid;
    const char *attachment_file_url;
    GSList *attachments = NULL;
    GSList *attachments_new = NULL;
    GSList *siter = NULL;
    CamelMimePart *part, *alternative;
    CamelMultipart *multipart, *nested_multipart;
    CamelDataWrapper *content, *alternative_content;
    int i, j, num_parts, num_alternatives;
    gboolean found_ical = FALSE;

    attachment_store =
        g_object_get_data (G_OBJECT (object), "attachment-store");

    part = CAMEL_MIME_PART (msg);
    content = camel_medium_get_content_object (CAMEL_MEDIUM (part));

    if (content == NULL) {
        return FALSE;
    }

    mime_type = camel_content_type_simple (content->mime_type);

    if (CAMEL_IS_MULTIPART (content)) {
        multipart = (CamelMultipart *) content;
        num_parts = (int) camel_multipart_get_number (multipart);

        for (i = 0; i < num_parts; i++) {
            part = camel_multipart_get_part (multipart, i);
            content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
            mime_type = camel_content_type_simple (content->mime_type);
            mime_filename = camel_mime_part_get_filename (part);
            content_disposition = camel_mime_part_get_disposition (part);

            if (CAMEL_IS_MULTIPART (content)) {
                nested_multipart = (CamelMultipart *) content;
                num_alternatives =
                    (int) camel_multipart_get_number (nested_multipart);
                for (j = 0; j < num_alternatives; j++) {
                    alternative =
                        camel_multipart_get_part (nested_multipart, j);
                    alternative_content =
                        camel_medium_get_content_object (CAMEL_MEDIUM
                                                         (alternative));
                    alternative_mime_type =
                        camel_content_type_simple (alternative_content->
                                                   mime_type);
                    if (g_str_equal (alternative_mime_type, "text/calendar")
                        && found_ical == FALSE) {
                        if (set_ical_from_mime_part (alternative, object) ==
                            TRUE) {
                            e_cal_component_get_uid (E_CAL_COMPONENT (object),
                                                     &cuid);
                            e_cal_component_get_attachment_list (E_CAL_COMPONENT
                                                                 (object),
                                                                 &attachments);
                            /* we are only interested in the first ical body part */
                            found_ical = TRUE;
                        }
                    }
                }
            } else if (g_str_equal (mime_type, "text/calendar")
                       && found_ical == FALSE) {
                if (set_ical_from_mime_part (part, object) == TRUE) {
                    e_cal_component_get_uid (E_CAL_COMPONENT (object), &cuid);
                    e_cal_component_get_attachment_list (E_CAL_COMPONENT
                                                         (object),
                                                         &attachments);
                    /* we are only interested in the first ical body part */
                    found_ical = TRUE;
                }
            } else if (content_disposition
                       && strcmp (content_disposition, "attachment") == 0) {
                cid = camel_mime_part_get_content_id (part);
                if (cid != NULL) {
                    for (siter = attachments; siter; siter = siter->next) {
                        if (strstr (siter->data, cid) ==
                            (char *) (siter->data) + 4) {
                            attachment_file_url =
                                save_attachment (part, cuid, attachment_store);
                            if (attachment_file_url != NULL) {
                                attachments_new =
                                    g_slist_append (attachments_new,
                                                    g_strdup
                                                    (attachment_file_url));
                            }
                        }
                    }
                }
            } else {
                g_print ("XXXXX Unhandled mime part: %s\n", mime_type);
            }
        }
    } else {
        /* just a simple ical message */
        if (g_str_equal (mime_type, "text/calendar")) {
            set_ical_from_mime_part (part, object);
        }
    }

    if (attachments_new != NULL) {
        e_cal_component_set_attachment_list (E_CAL_COMPONENT (object),
                                             attachments_new);
    }

    msgid = camel_mime_message_get_message_id (msg);

    scalix_appointment_unset (SCALIX_APPOINTMENT (object), X_SCALIX_MSG_ID);

    scalix_appointment_set (SCALIX_APPOINTMENT (object),
                            X_SCALIX_MSG_ID, msgid);

    return TRUE;
}
void
e_mail_session_send_to (EMailSession *session,
                        CamelMimeMessage *message,
                        gint io_priority,
                        GCancellable *cancellable,
                        CamelFilterGetFolderFunc get_folder_func,
                        gpointer get_folder_data,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;
	CamelAddress *from;
	CamelAddress *recipients;
	CamelMedium *medium;
	CamelMessageInfo *info;
	CamelService *transport;
	GPtrArray *post_to_uris;
	struct _camel_header_raw *xev;
	struct _camel_header_raw *header;
	const gchar *resent_from;
	GError *error = NULL;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	medium = CAMEL_MEDIUM (message);

	camel_medium_set_header (medium, "X-Mailer", X_MAILER);

	/* Do this before removing "X-Evolution" headers. */
	transport = e_mail_session_ref_transport_for_message (
		session, message);

	xev = mail_tool_remove_xevolution_headers (message);

	/* Extract directives from X-Evolution headers. */

	post_to_uris = g_ptr_array_new ();
	for (header = xev; header != NULL; header = header->next) {
		gchar *folder_uri;

		if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
			continue;

		folder_uri = g_strstrip (g_strdup (header->value));
		g_ptr_array_add (post_to_uris, folder_uri);
	}

	/* Collect sender and recipients from headers. */

	from = (CamelAddress *) camel_internet_address_new ();
	recipients = (CamelAddress *) camel_internet_address_new ();
	resent_from = camel_medium_get_header (medium, "Resent-From");

	if (resent_from != NULL) {
		const CamelInternetAddress *addr;
		const gchar *type;

		camel_address_decode (from, resent_from);

		type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

	} else {
		const CamelInternetAddress *addr;
		const gchar *type;

		addr = camel_mime_message_get_from (message);
		camel_address_copy (from, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));
	}

	/* Miscellaneous preparations. */

	info = camel_message_info_new_from_header (
		NULL, CAMEL_MIME_PART (message)->headers);
	((CamelMessageInfoBase *) info)->size =
		get_message_size (message, cancellable);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* expand, or remove empty, group addresses */
	em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients));

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (AsyncContext);
	context->message = g_object_ref (message);
	context->io_priority = io_priority;
	context->from = from;
	context->recipients = recipients;
	context->info = info;
	context->xev = xev;
	context->post_to_uris = post_to_uris;
	context->transport = transport;

	if (G_IS_CANCELLABLE (cancellable))
		context->cancellable = g_object_ref (cancellable);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
		CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
	if (context->driver != NULL && get_folder_func)
		camel_filter_driver_set_folder_func (
			context->driver, get_folder_func, get_folder_data);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (
		context->cancellable, _("Sending message"));

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback,
		user_data, e_mail_session_send_to);

	g_simple_async_result_set_check_cancellable (simple, cancellable);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, (GSimpleAsyncThreadFunc)
		mail_session_send_to_thread,
		context->io_priority,
		context->cancellable);

	g_object_unref (simple);
}
Esempio n. 10
0
static gboolean
do_mail_to_event (AsyncData *data)
{
	EClient *client;
	CamelFolder *folder = data->folder;
	GPtrArray *uids = data->uids;
	GError *error = NULL;

	client = e_client_cache_get_client_sync (data->client_cache,
		data->source, data->extension_name, 30, NULL, &error);

	/* Sanity check. */
	g_return_val_if_fail (
		((client != NULL) && (error == NULL)) ||
		((client == NULL) && (error != NULL)), TRUE);

	if (error != NULL) {
		report_error_idle (_("Cannot open calendar. %s"), error->message);
	} else if (e_client_is_readonly (E_CLIENT (client))) {
		switch (data->source_type) {
		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
			report_error_idle (_("Selected calendar is read only, thus cannot create event there. Select other calendar, please."), NULL);
			break;
		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
			report_error_idle (_("Selected task list is read only, thus cannot create task there. Select other task list, please."), NULL);
			break;
		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
			report_error_idle (_("Selected memo list is read only, thus cannot create memo there. Select other memo list, please."), NULL);
			break;
		default:
			g_warn_if_reached ();
			break;
		}
	} else {
		gint i;
		ECalComponentDateTime dt, dt2;
		struct icaltimetype tt, tt2;
		struct _manage_comp *oldmc = NULL;

		#define cache_backend_prop(prop) { \
			gchar *val = NULL; \
			e_client_get_backend_property_sync (E_CLIENT (client), prop, &val, NULL, NULL); \
			g_free (val); \
		}

		/* precache backend properties, thus editor have them ready when needed */
		cache_backend_prop (CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
		cache_backend_prop (CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS);
		cache_backend_prop (CAL_BACKEND_PROPERTY_DEFAULT_OBJECT);
		e_client_get_capabilities (E_CLIENT (client));

		#undef cache_backend_prop

		/* set start day of the event as today, without time - easier than looking for a calendar's time zone */
		tt = icaltime_today ();
		dt.value = &tt;
		dt.tzid = NULL;

		tt2 = tt;
		icaltime_adjust (&tt2, 1, 0, 0, 0);
		dt2.value = &tt2;
		dt2.tzid = NULL;

		for (i = 0; i < (uids ? uids->len : 0); i++) {
			CamelMimeMessage *message;
			ECalComponent *comp;
			ECalComponentText text;
			icalproperty *icalprop;
			icalcomponent *icalcomp;
			struct _manage_comp *mc;

			/* retrieve the message from the CamelFolder */
			/* FIXME Not passing a GCancellable or GError. */
			message = camel_folder_get_message_sync (
				folder, g_ptr_array_index (uids, i),
				NULL, NULL);
			if (!message) {
				continue;
			}

			comp = e_cal_component_new ();

			switch (data->source_type) {
			case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
				break;
			case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
				break;
			case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
				break;
			default:
				g_warn_if_reached ();
				break;
			}

			e_cal_component_set_uid (comp, camel_mime_message_get_message_id (message));
			e_cal_component_set_dtstart (comp, &dt);

			if (data->source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS) {
				/* make it an all-day event */
				e_cal_component_set_dtend (comp, &dt2);
			}

			/* set the summary */
			text.value = camel_mime_message_get_subject (message);
			text.altrep = NULL;
			e_cal_component_set_summary (comp, &text);

			/* set all fields */
			if (data->selected_text) {
				GSList sl;

				text.value = data->selected_text;
				text.altrep = NULL;
				sl.next = NULL;
				sl.data = &text;

				e_cal_component_set_description_list (comp, &sl);
			} else
				set_description (comp, message);

			if (data->with_attendees) {
				gchar *organizer;

				/* set actual user as organizer, to be able to change event's properties */
				organizer = set_organizer (comp, data->folder);
				set_attendees (comp, message, organizer);
				g_free (organizer);
			}

			/* set attachment files */
			set_attachments (E_CAL_CLIENT (client), comp, message);

			/* priority */
			set_priority (comp, CAMEL_MIME_PART (message));

			/* no need to increment a sequence number, this is a new component */
			e_cal_component_abort_sequence (comp);

			icalcomp = e_cal_component_get_icalcomponent (comp);

			icalprop = icalproperty_new_x ("1");
			icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR");
			icalcomponent_add_property (icalcomp, icalprop);

			mc = g_new0 (struct _manage_comp, 1);
			mc->client = g_object_ref (client);
			mc->comp = g_object_ref (comp);
			g_mutex_init (&mc->mutex);
			g_cond_init (&mc->cond);
			mc->mails_count = uids->len;
			mc->mails_done = i + 1; /* Current task */
			mc->editor_title = NULL;
			mc->can_continue = TRUE;

			if (oldmc) {
				/* Wait for user to quit the editor created in previous iteration
				 * before displaying next one */
				gboolean can_continue;
				g_mutex_lock (&oldmc->mutex);
				g_cond_wait (&oldmc->cond, &oldmc->mutex);
				g_mutex_unlock (&oldmc->mutex);
				can_continue = oldmc->can_continue;
				free_manage_comp_struct (oldmc);
				oldmc = NULL;

				if (!can_continue)
					break;
			}

			e_cal_client_get_object_sync (
				E_CAL_CLIENT (client),
				icalcomponent_get_uid (icalcomp),
				NULL, &mc->stored_comp, NULL, NULL);

			/* Prioritize ahead of GTK+ redraws. */
			g_idle_add_full (
				G_PRIORITY_HIGH_IDLE,
				(GSourceFunc) do_manage_comp_idle, mc, NULL);

			oldmc = mc;

			g_object_unref (comp);
			g_object_unref (message);

		}

		/* Wait for the last editor and then clean up */
		if (oldmc) {
			g_mutex_lock (&oldmc->mutex);
			g_cond_wait (&oldmc->cond, &oldmc->mutex);
			g_mutex_unlock (&oldmc->mutex);
			free_manage_comp_struct (oldmc);
		}
	}

	/* free memory */
	if (client != NULL)
		g_object_unref (client);
	g_ptr_array_unref (uids);
	g_object_unref (folder);

	g_object_unref (data->client_cache);
	g_object_unref (data->source);
	g_free (data->selected_text);
	g_free (data);
	data = NULL;

	if (error != NULL)
		g_error_free (error);

	return TRUE;
}
Esempio n. 11
0
gboolean
camel_ews_utils_create_mime_message (EEwsConnection *cnc,
                                     const gchar *disposition,
                                     const EwsFolderId *fid,
                                     CamelMimeMessage *message,
                                     CamelMessageInfo *info,
                                     CamelAddress *from,
				     CamelAddress *recipients,
                                     gchar **itemid,
                                     gchar **changekey,
                                     GCancellable *cancellable,
                                     GError **error)
{
	struct _create_mime_msg_data *create_data;
	GSList *ids;
	EEwsItem *item;
	const EwsId *ewsid;
	gchar *restore_from = NULL;
	gboolean res;

	create_data = g_new0 (struct _create_mime_msg_data, 1);

	create_data->message = message;
	create_data->info = info;
	create_data->from = from;
	create_data->recipients = recipients;

	if (g_strcmp0 (disposition, "SendOnly") == 0 ||
	    g_strcmp0 (disposition, "SendAndSaveCopy") == 0) {
		struct _camel_header_raw *header;

		for (header = CAMEL_MIME_PART (message)->headers; header; header = header->next) {
			if (header->name && g_ascii_strcasecmp (header->name, "From") == 0) {
				restore_from = header->value;
				header->value = g_strdup ("");
				break;
			}
		}
	}

	res = e_ews_connection_create_items_sync (
		cnc, EWS_PRIORITY_MEDIUM,
		disposition, NULL, fid,
		create_mime_message_cb, create_data,
		&ids, cancellable, error);

	if (restore_from) {
		struct _camel_header_raw *header;

		for (header = CAMEL_MIME_PART (message)->headers; header; header = header->next) {
			if (header->name && g_ascii_strcasecmp (header->name, "From") == 0) {
				g_free (header->value);
				header->value = restore_from;
				break;
			}
		}
	}

	if (!res || (!itemid && !changekey))
		return res;

	item = (EEwsItem *) ids->data;
	if (!item || !(ewsid = e_ews_item_get_id (item))) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("CreateItem call failed to return ID for new message"));
		return FALSE;
	}

	if (itemid)
		*itemid = g_strdup (ewsid->id);
	if (changekey)
		*changekey = g_strdup (ewsid->change_key);

	g_object_unref (item);
	g_slist_free (ids);
	return TRUE;
}
Esempio n. 12
0
static void
create_mime_message_cb (ESoapMessage *msg,
                        gpointer user_data)
{
	struct _create_mime_msg_data *create_data = user_data;
	CamelStream *mem, *filtered;
	CamelMimeFilter *filter;
	CamelContentType *content_type;
	GByteArray *bytes;
	gchar *base64;
	gint msgflag;
	guint32 message_camel_flags = 0;

	if (create_data->info)
		message_camel_flags = camel_message_info_flags (create_data->info);
		
	e_soap_message_start_element (msg, "Message", NULL, NULL);
	e_soap_message_start_element (msg, "MimeContent", NULL, NULL);

	/* This is horrid. We really need to extend ESoapMessage to allow us
	 * to stream this directly rather than storing it in RAM. Which right
	 * now we are doing about four times: the GByteArray in the mem stream,
	 * then the base64 version, then the xmlDoc, then the soup request. */
	camel_mime_message_set_best_encoding (
		create_data->message,
		CAMEL_BESTENC_GET_ENCODING,
		CAMEL_BESTENC_8BIT);

	mem = camel_stream_mem_new ();
	filtered = camel_stream_filter_new (mem);

	filter = camel_mime_filter_crlf_new (
		CAMEL_MIME_FILTER_CRLF_ENCODE,
		CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
	camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered), filter);
	g_object_unref (filter);

	camel_data_wrapper_write_to_stream_sync (
		CAMEL_DATA_WRAPPER (create_data->message),
		filtered, NULL, NULL);
	camel_stream_flush (filtered, NULL, NULL);
	camel_stream_flush (mem, NULL, NULL);
	bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem));

	base64 = g_base64_encode (bytes->data, bytes->len);
	g_object_unref (mem);
	g_object_unref (filtered);

	e_soap_message_write_string (msg, base64);
	g_free (base64);

	e_soap_message_end_element (msg); /* MimeContent */

	content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (create_data->message));
	if (content_type && camel_content_type_is (content_type, "multipart", "report") &&
	    camel_content_type_param (content_type, "report-type") &&
	    g_ascii_strcasecmp (camel_content_type_param (content_type, "report-type"), "disposition-notification") == 0) {
		/* it's a disposition notification reply, set ItemClass too */
		e_soap_message_start_element (msg, "ItemClass", NULL, NULL);
		e_soap_message_write_string (msg, "REPORT.IPM.NOTE.IPNRN");
		e_soap_message_end_element (msg); /* ItemClass */
	}

	e_ews_message_write_string_parameter_with_attribute (
			msg,
			"Importance",
			NULL,
			(message_camel_flags & CAMEL_MESSAGE_FLAGGED) != 0 ? "High" : "Normal",
			NULL,
			NULL);

	/* more MAPI crap.  You can't just set the IsDraft property
	 * here you have to use the MAPI MSGFLAG_UNSENT extended
	 * property Further crap is that Exchange 2007 assumes when it
	 * sees this property that you're setting the value to 0
	 * ... it never checks */
	msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */
	if ((message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0)
		msgflag |= MAPI_MSGFLAG_UNSENT;

	e_ews_message_add_extended_property_tag_int (msg, 0x0e07, msgflag);

	if ((message_camel_flags & (CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_ANSWERED)) != 0) {
		gint icon;

		icon = (message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 0x105 : 0x106;

		e_ews_message_add_extended_property_tag_int (msg, 0x1080, icon);
	}

	if (create_data->info) {
		const gchar *followup, *completed, *dueby;
		time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0;

		/* follow-up flags */
		followup = camel_message_info_user_tag (create_data->info, "follow-up");
		completed = camel_message_info_user_tag (create_data->info, "completed-on");
		dueby = camel_message_info_user_tag (create_data->info, "due-by");

		if (followup && !*followup)
			followup = NULL;

		if (completed && *completed)
			completed_tt = camel_header_decode_date (completed, NULL);

		if (dueby && *dueby)
			dueby_tt = camel_header_decode_date (dueby, NULL);

		/* PidTagFlagStatus */
		e_ews_message_add_extended_property_tag_int (msg, 0x1090,
			followup ? (completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /* followupFlagged */) : 0x0);

		if (followup) {
			/* PidLidFlagRequest */
			e_ews_message_add_extended_property_distinguished_tag_string (msg, "Common", 0x8530, followup);

			/* PidTagToDoItemFlags */
			e_ews_message_add_extended_property_tag_int (msg, 0x0e2b, 1);
		}

		if (followup && completed_tt != (time_t) 0) {
			/* minute precision */
			completed_tt = completed_tt - (completed_tt % 60);

			/* PidTagFlagCompleteTime */
			e_ews_message_add_extended_property_tag_time (msg, 0x1091, completed_tt);

			/* PidLidTaskDateCompleted */
			e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x810f, completed_tt);

			/* PidLidTaskStatus */
			e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 2);

			/* PidLidPercentComplete */
			e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 1.0);

			/* PidLidTaskComplete */
			e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, TRUE);
		}

		if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) {
			/* PidLidTaskStatus */
			e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 0);

			/* PidLidPercentComplete */
			e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 0.0);

			/* PidLidTaskDueDate */
			e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x8105, dueby_tt);

			/* PidLidTaskComplete */
			e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, FALSE);
		}
	}

	if (create_data->recipients) {
		GHashTable *recip_to, *recip_cc, *recip_bcc;

		recip_to = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
		recip_cc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
		recip_bcc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
	
		filter_recipients (create_data->message, create_data->recipients, recip_to, recip_cc, recip_bcc);

		write_recipients (msg, "ToRecipients", recip_to);
		write_recipients (msg, "CcRecipients", recip_cc);
		write_recipients (msg, "BccRecipients", recip_bcc);

		g_hash_table_destroy (recip_to);
		g_hash_table_destroy (recip_cc);
		g_hash_table_destroy (recip_bcc);
	}

	e_ews_message_write_string_parameter_with_attribute (
			msg,
			"IsRead",
			NULL,
			(message_camel_flags & CAMEL_MESSAGE_SEEN) != 0 ? "true" : "false",
			NULL,
			NULL);

	e_soap_message_end_element (msg); /* Message */

	g_free (create_data);
}
static gboolean
sendmail_send_to_sync (CamelTransport *transport,
                       CamelMimeMessage *message,
                       CamelAddress *from,
                       CamelAddress *recipients,
		       gboolean *out_sent_message_saved,
                       GCancellable *cancellable,
                       GError **error)
{
	CamelHeaderRaw *header, *savedbcc, *n, *tail;
	const gchar *from_addr, *addr;
	GPtrArray *argv_arr;
	gint i, len, fd[2], nullfd, wstat;
	CamelStream *filter;
	CamelMimeFilter *crlf;
	sigset_t mask, omask;
	CamelStream *out;
	CamelSendmailSettings *settings;
	const gchar *binary = SENDMAIL_PATH;
	gchar *custom_binary = NULL, *custom_args = NULL;
	gboolean success;
	pid_t pid;

	success = camel_internet_address_get (
		CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr);

	if (!success) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Failed to read From address"));
		return FALSE;
	}

	settings = CAMEL_SENDMAIL_SETTINGS (camel_service_ref_settings (CAMEL_SERVICE (transport)));

	if (!camel_sendmail_settings_get_send_in_offline (settings)) {
		CamelSession *session;
		gboolean is_online;

		session = camel_service_ref_session (CAMEL_SERVICE (transport));
		is_online = session && camel_session_get_online (session);
		g_clear_object (&session);

		if (!is_online) {
			g_set_error (
				error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
				_("Message send in offline mode is disabled"));
			return FALSE;
		}
	}

	if (camel_sendmail_settings_get_use_custom_binary (settings)) {
		custom_binary = camel_sendmail_settings_dup_custom_binary (settings);
		if (custom_binary && *custom_binary)
			binary = custom_binary;
	}

	if (camel_sendmail_settings_get_use_custom_args (settings)) {
		custom_args = camel_sendmail_settings_dup_custom_args (settings);
		/* means no arguments used */
		if (!custom_args)
			custom_args = g_strdup ("");
	}

	g_object_unref (settings);

	len = camel_address_length (recipients);
	for (i = 0; i < len; i++) {
		success = camel_internet_address_get (
			CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr);

		if (!success) {
			g_set_error (
				error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
				_("Could not parse recipient list"));
			g_free (custom_binary);
			g_free (custom_args);

			return FALSE;
		}
	}

	argv_arr = parse_sendmail_args (
		binary,
		custom_args ? custom_args : "-i -f %F -- %R",
		from_addr,
		recipients);

	if (!argv_arr) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Could not parse arguments"));

		g_free (custom_binary);
		g_free (custom_args);

		return FALSE;
	}

	/* unlink the bcc headers */
	savedbcc = NULL;
	tail = (CamelHeaderRaw *) &savedbcc;

	header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers;
	n = header->next;
	while (n != NULL) {
		if (!g_ascii_strcasecmp (n->name, "Bcc")) {
			header->next = n->next;
			tail->next = n;
			n->next = NULL;
			tail = n;
		} else {
			header = n;
		}

		n = header->next;
	}

	if (pipe (fd) == -1) {
		g_set_error (
			error, G_IO_ERROR,
			g_io_error_from_errno (errno),
			_("Could not create pipe to '%s': %s: "
			"mail not sent"), binary, g_strerror (errno));

		/* restore the bcc headers */
		header->next = savedbcc;
		g_free (custom_binary);
		g_free (custom_args);
		g_ptr_array_free (argv_arr, TRUE);

		return FALSE;
	}

	/* Block SIGCHLD so the calling application doesn't notice
	 * sendmail exiting before we do.
	 */
	sigemptyset (&mask);
	sigaddset (&mask, SIGCHLD);
	sigprocmask (SIG_BLOCK, &mask, &omask);

	pid = fork ();
	switch (pid) {
	case -1:
		g_set_error (
			error, G_IO_ERROR,
			g_io_error_from_errno (errno),
			_("Could not fork '%s': %s: "
			"mail not sent"), binary, g_strerror (errno));
		close (fd[0]);
		close (fd[1]);
		sigprocmask (SIG_SETMASK, &omask, NULL);

		/* restore the bcc headers */
		header->next = savedbcc;
		g_free (custom_binary);
		g_free (custom_args);
		g_ptr_array_free (argv_arr, TRUE);

		return FALSE;
	case 0:
		/* Child process */
		nullfd = open ("/dev/null", O_RDWR);
		dup2 (fd[0], STDIN_FILENO);
		if (nullfd != -1) {
			/*dup2 (nullfd, STDOUT_FILENO);
			  dup2 (nullfd, STDERR_FILENO);*/
			close (nullfd);
		}
		close (fd[1]);

		execv (binary, (gchar **) argv_arr->pdata);
		_exit (255);
	}

	g_ptr_array_free (argv_arr, TRUE);

	/* Parent process. Write the message out. */
	close (fd[0]);
	out = camel_stream_fs_new_with_fd (fd[1]);

	/* XXX Workaround for lame sendmail implementations
	 *     that can't handle CRLF eoln sequences. */
	filter = camel_stream_filter_new (out);
	crlf = camel_mime_filter_crlf_new (
		CAMEL_MIME_FILTER_CRLF_DECODE,
		CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
	camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), crlf);
	g_object_unref (crlf);
	g_object_unref (out);

	out = (CamelStream *) filter;
	if (camel_data_wrapper_write_to_stream_sync (
		CAMEL_DATA_WRAPPER (message), out, cancellable, error) == -1
	    || camel_stream_close (out, cancellable, error) == -1) {
		g_object_unref (out);
		g_prefix_error (error, _("Could not send message: "));

		/* Wait for sendmail to exit. */
		while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR)
			;

		sigprocmask (SIG_SETMASK, &omask, NULL);

		/* restore the bcc headers */
		header->next = savedbcc;
		g_free (custom_binary);
		g_free (custom_args);

		return FALSE;
	}

	g_object_unref (out);

	/* Wait for sendmail to exit. */
	while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR)
		;

	sigprocmask (SIG_SETMASK, &omask, NULL);

	/* restore the bcc headers */
	header->next = savedbcc;

	if (!WIFEXITED (wstat)) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("'%s' exited with signal %s: mail not sent."),
			binary, g_strsignal (WTERMSIG (wstat)));
		g_free (custom_binary);
		g_free (custom_args);

		return FALSE;
	} else if (WEXITSTATUS (wstat) != 0) {
		if (WEXITSTATUS (wstat) == 255) {
			g_set_error (
				error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
				_("Could not execute '%s': mail not sent."),
				binary);
		} else {
			g_set_error (
				error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
				_("'%s' exited with status %d: "
				"mail not sent."),
				binary, WEXITSTATUS (wstat));
		}
		g_free (custom_binary);
		g_free (custom_args);

		return FALSE;
	}

	g_free (custom_binary);
	g_free (custom_args);

	return TRUE;
}
static gboolean
nntp_folder_append_message_sync (CamelFolder *folder,
                                 CamelMimeMessage *message,
                                 CamelMessageInfo *info,
                                 gchar **appended_uid,
                                 GCancellable *cancellable,
                                 GError **error)
{
	CamelStore *parent_store;
	CamelNNTPStore *nntp_store;
	CamelNNTPStream *nntp_stream = NULL;
	CamelStream *filtered_stream;
	CamelMimeFilter *crlffilter;
	gint ret;
	guint u;
	struct _camel_header_raw *header, *savedhdrs, *n, *tail;
	const gchar *full_name;
	gchar *group, *line;
	gboolean success = TRUE;
	GError *local_error = NULL;

	full_name = camel_folder_get_full_name (folder);
	parent_store = camel_folder_get_parent_store (folder);

	nntp_store = CAMEL_NNTP_STORE (parent_store);

	/* send 'POST' command */
	ret = camel_nntp_command (
		nntp_store, cancellable, error, NULL, &line, "post");
	if (ret != 340) {
		if (ret == 440) {
			g_set_error (
				error, CAMEL_FOLDER_ERROR,
				CAMEL_FOLDER_ERROR_INSUFFICIENT_PERMISSION,
				_("Posting failed: %s"), line);
			success = FALSE;
		} else if (ret != -1) {
			g_set_error (
				error, CAMEL_ERROR,
				CAMEL_ERROR_GENERIC,
				_("Posting failed: %s"), line);
			success = FALSE;
		}
		goto exit;
	}

	/* the 'Newsgroups: ' header */
	group = g_strdup_printf ("Newsgroups: %s\r\n", full_name);

	/* remove mail 'To', 'CC', and 'BCC' headers */
	savedhdrs = NULL;
	tail = (struct _camel_header_raw *) &savedhdrs;

	header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
	n = header->next;
	while (n != NULL) {
		if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") || !g_ascii_strcasecmp (n->name, "Bcc")) {
			header->next = n->next;
			tail->next = n;
			n->next = NULL;
			tail = n;
		} else {
			header = n;
		}

		n = header->next;
	}

	nntp_stream = camel_nntp_store_ref_stream (nntp_store);

	/* setup stream filtering */
	filtered_stream = camel_stream_filter_new (CAMEL_STREAM (nntp_stream));
	crlffilter = camel_mime_filter_crlf_new (
		CAMEL_MIME_FILTER_CRLF_ENCODE,
		CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
	camel_stream_filter_add (
		CAMEL_STREAM_FILTER (filtered_stream), crlffilter);
	g_object_unref (crlffilter);

	/* write the message */
	if (local_error == NULL)
		camel_stream_write (
			CAMEL_STREAM (nntp_stream),
			group, strlen (group),
			cancellable, &local_error);
	if (local_error == NULL)
		camel_data_wrapper_write_to_stream_sync (
			CAMEL_DATA_WRAPPER (message),
			filtered_stream, cancellable, &local_error);
	if (local_error == NULL)
		camel_stream_flush (
			filtered_stream, cancellable, &local_error);
	if (local_error == NULL)
		camel_stream_write (
			CAMEL_STREAM (nntp_stream),
			"\r\n.\r\n", 5,
			cancellable, &local_error);
	if (local_error == NULL)
		camel_nntp_stream_line (
			nntp_stream, (guchar **) &line,
			&u, cancellable, &local_error);
	if (local_error == NULL && atoi (line) != 240)
		local_error = g_error_new_literal (
			CAMEL_ERROR, CAMEL_ERROR_GENERIC, line);

	if (local_error != NULL) {
		g_propagate_prefixed_error (
			error, local_error, _("Posting failed: "));
		success = FALSE;
	}

	g_object_unref (filtered_stream);
	g_free (group);
	header->next = savedhdrs;

exit:
	g_clear_object (&nntp_stream);

	return success;
}
static void
nntp_folder_append_message_online (CamelFolder *folder, CamelMimeMessage *mime_message,
				   const CamelMessageInfo *info, char **appended_uid,
				   CamelException *ex)
{
	CamelNNTPStore *nntp_store = (CamelNNTPStore *) folder->parent_store;
	CamelStream *stream = (CamelStream*)nntp_store->stream;
	CamelStreamFilter *filtered_stream;
	CamelMimeFilter *crlffilter;
	int ret;
	unsigned int u;
	struct _camel_header_raw *header, *savedhdrs, *n, *tail;
	char *group, *line;

	CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);

	/* send 'POST' command */
	ret = camel_nntp_command (nntp_store, ex, NULL, &line, "post");
	if (ret != 340) {
		if (ret == 440)
			camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
					      _("Posting failed: %s"), line);
		else if (ret != -1)
			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
					      _("Posting failed: %s"), line);
		CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
		return;
	}

	/* the 'Newsgroups: ' header */
	group = g_strdup_printf ("Newsgroups: %s\r\n", folder->full_name);

	/* setup stream filtering */
	crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
	filtered_stream = camel_stream_filter_new_with_stream (stream);
	camel_stream_filter_add (filtered_stream, crlffilter);
	camel_object_unref (crlffilter);

	/* remove mail 'To', 'CC', and 'BCC' headers */
	savedhdrs = NULL;
	tail = (struct _camel_header_raw *) &savedhdrs;

	header = (struct _camel_header_raw *) &CAMEL_MIME_PART (mime_message)->headers;
	n = header->next;
	while (n != NULL) {
		if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") || !g_ascii_strcasecmp (n->name, "Bcc")) {
			header->next = n->next;
			tail->next = n;
			n->next = NULL;
			tail = n;
		} else {
			header = n;
		}

		n = header->next;
	}

	/* write the message */
	if (camel_stream_write(stream, group, strlen(group)) == -1
	    || camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), CAMEL_STREAM (filtered_stream)) == -1
	    || camel_stream_flush (CAMEL_STREAM (filtered_stream)) == -1
	    || camel_stream_write (stream, "\r\n.\r\n", 5) == -1
	    || (ret = camel_nntp_stream_line (nntp_store->stream, (unsigned char **)&line, &u)) == -1) {
		if (errno == EINTR)
			camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled"));
		else
			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), g_strerror (errno));
	} else if (atoi(line) != 240) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), line);
	}

	camel_object_unref (filtered_stream);
	g_free(group);
	header->next = savedhdrs;

	CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);

	return;
}
Esempio n. 16
0
static CamelSExpResult *
check_header (struct _CamelSExp *f,
              gint argc,
              struct _CamelSExpResult **argv,
              FilterMessageSearch *fms,
              camel_search_match_t how)
{
	gboolean matched = FALSE;
	CamelSExpResult *r;
	gint i;

	if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING) {
		gchar *name = argv[0]->value.string;

		/* shortcut: a match for "" against any header always matches */
		for (i = 1; i < argc && !matched; i++)
			matched = argv[i]->type == CAMEL_SEXP_RES_STRING && argv[i]->value.string[0] == 0;

		if (g_ascii_strcasecmp (name, "x-camel-mlist") == 0) {
			const gchar *list = camel_message_info_mlist (fms->info);

			if (list) {
				for (i = 1; i < argc && !matched; i++) {
					if (argv[i]->type == CAMEL_SEXP_RES_STRING)
						matched = camel_search_header_match (list, argv[i]->value.string, how, CAMEL_SEARCH_TYPE_MLIST, NULL);
				}
			}
		} else if (fms->message || !check_header_in_message_info (fms->info, argc, argv, how, &matched)) {
			CamelMimeMessage *message;
			CamelMimePart *mime_part;
			struct _camel_header_raw *header;
			const gchar *charset = NULL;
			camel_search_t type = CAMEL_SEARCH_TYPE_ENCODED;
			CamelContentType *ct;

			message = camel_filter_search_get_message (fms, f);
			mime_part = CAMEL_MIME_PART (message);

			/* FIXME: what about Resent-To, Resent-Cc and Resent-From? */
			if (g_ascii_strcasecmp ("to", name) == 0 || g_ascii_strcasecmp ("cc", name) == 0 || g_ascii_strcasecmp ("from", name) == 0)
				type = CAMEL_SEARCH_TYPE_ADDRESS_ENCODED;
			else if (message) {
				ct = camel_mime_part_get_content_type (mime_part);
				if (ct) {
					charset = camel_content_type_param (ct, "charset");
					charset = camel_iconv_charset_name (charset);
				}
			}

			for (header = mime_part->headers; header && !matched; header = header->next) {
				/* empty name means any header */
				if (!name || !*name || !g_ascii_strcasecmp (header->name, name)) {
					for (i = 1; i < argc && !matched; i++) {
						if (argv[i]->type == CAMEL_SEXP_RES_STRING)
							matched = camel_search_header_match (header->value, argv[i]->value.string, how, type, charset);
					}
				}
			}
		}
	}

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
	r->value.boolean = matched;

	return r;
}
Esempio n. 17
0
static void
set_description (ECalComponent *comp,
                 CamelMimeMessage *message)
{
	CamelDataWrapper *content;
	CamelStream *stream;
	CamelContentType *type;
	CamelMimePart *mime_part = CAMEL_MIME_PART (message);
	ECalComponentText *text = NULL;
	GByteArray *byte_array;
	GSList *sl = NULL;
	gchar *str, *convert_str = NULL;
	gsize bytes_read, bytes_written;
	gint count = 2;

	content = camel_medium_get_content ((CamelMedium *) message);
	if (!content)
		return;

	/*
	 * Get non-multipart content from multipart message.
	 */
	while (CAMEL_IS_MULTIPART (content) && count > 0) {
		mime_part = camel_multipart_get_part (CAMEL_MULTIPART (content), 0);
		content = camel_medium_get_content (CAMEL_MEDIUM (mime_part));
		count--;
	}

	if (!mime_part)
		return;

	type = camel_mime_part_get_content_type (mime_part);
	if (!camel_content_type_is (type, "text", "plain"))
		return;

	byte_array = g_byte_array_new ();
	stream = camel_stream_mem_new_with_byte_array (byte_array);
	camel_data_wrapper_decode_to_stream_sync (content, stream, NULL, NULL);
	str = g_strndup ((gchar *) byte_array->data, byte_array->len);
	g_object_unref (stream);

	/* convert to UTF-8 string */
	if (str && content->mime_type->params && content->mime_type->params->value) {
		convert_str = g_convert (
			str, strlen (str),
			"UTF-8", content->mime_type->params->value,
			&bytes_read, &bytes_written, NULL);
	}

	text = g_new0 (ECalComponentText, 1);
	if (convert_str)
		text->value = prepend_from (message, &convert_str);
	else
		text->value = prepend_from (message, &str);
	text->altrep = NULL;
	sl = g_slist_append (sl, text);

	e_cal_component_set_description_list (comp, sl);

	g_free (str);
	if (convert_str)
		g_free (convert_str);
	e_cal_component_free_text_list (sl);
}
static CamelSExpResult *
junk_test (struct _CamelSExp *f,
           gint argc,
           struct _CamelSExpResult **argv,
           FilterMessageSearch *fms)
{
	CamelSExpResult *r;
	CamelMessageInfo *info = fms->info;
	CamelJunkFilter *junk_filter;
	CamelMessageFlags flags;
	CamelMimeMessage *message;
	CamelJunkStatus status;
	const GHashTable *ht;
	const CamelHeaderParam *node;
	gboolean sender_is_known;
	gboolean message_is_junk = FALSE;
	GError *error = NULL;

	/* Check if the message is already classified. */

	flags = camel_message_info_get_flags (info);

	if (flags & CAMEL_MESSAGE_JUNK) {
		message_is_junk = TRUE;
		if (camel_debug ("junk"))
			printf (
				"Message has a Junk flag set already, "
				"skipping junk test...\n");
		goto done;
	}

	if (flags & CAMEL_MESSAGE_NOTJUNK) {
		if (camel_debug ("junk"))
			printf (
				"Message has a NotJunk flag set already, "
				"skipping junk test...\n");
		goto done;
	}

	/* If the sender is known, the message is not junk.
	   Do this before header test, to be able to override server-side set headers. */

	sender_is_known = camel_session_lookup_addressbook (
		fms->session, camel_message_info_get_from (info));
	if (camel_debug ("junk"))
		printf (
			"Sender '%s' in book? %d\n",
			camel_message_info_get_from (info),
			sender_is_known);
	if (sender_is_known)
		goto done;

	/* Check the headers for a junk designation. */

	ht = camel_session_get_junk_headers (fms->session);
	node = camel_message_info_get_headers (info);

	while (node != NULL) {
		const gchar *value = NULL;

		if (node->name != NULL)
			value = g_hash_table_lookup (
				(GHashTable *) ht, node->name);

		message_is_junk =
			(value != NULL) &&
			(camel_strstrcase (node->value, value) != NULL);

		if (message_is_junk) {
			if (camel_debug ("junk"))
				printf (
					"Message contains \"%s: %s\"",
					node->name, value);
			goto done;
		}

		node = node->next;
	}

	/* Not every message info has headers available, thus try headers of the message itself */
	message = camel_filter_search_get_message (fms, f);
	if (message) {
		struct _camel_header_raw *h;

		for (h = CAMEL_MIME_PART (message)->headers; h; h = h->next) {
			const gchar *value;

			if (!h->name)
				continue;

			value = g_hash_table_lookup ((GHashTable *) ht, h->name);
			if (!value)
				continue;

			message_is_junk = camel_strstrcase (h->value, value) != NULL;

			if (message_is_junk) {
				if (camel_debug ("junk"))
					printf (
						"Message contains \"%s: %s\"",
						h->name, value);
				goto done;
			}
		}
	} else {
		goto done;
	}

	/* Consult 3rd party junk filtering software. */

	junk_filter = camel_session_get_junk_filter (fms->session);
	if (junk_filter == NULL)
		goto done;

	status = camel_junk_filter_classify (
		junk_filter, message, fms->cancellable, &error);

	if (error == NULL) {
		const gchar *status_desc;

		switch (status) {
			case CAMEL_JUNK_STATUS_INCONCLUSIVE:
				status_desc = "inconclusive";
				message_is_junk = FALSE;
				break;
			case CAMEL_JUNK_STATUS_MESSAGE_IS_JUNK:
				status_desc = "junk";
				message_is_junk = TRUE;
				break;
			case CAMEL_JUNK_STATUS_MESSAGE_IS_NOT_JUNK:
				status_desc = "not junk";
				message_is_junk = FALSE;
				break;
			default:
				g_warn_if_reached ();
				status_desc = "invalid";
				message_is_junk = FALSE;
				break;
		}

		if (camel_debug ("junk"))
			printf (
				"Junk filter classification: %s\n",
				status_desc);
	} else {
		g_warn_if_fail (status == CAMEL_JUNK_STATUS_ERROR);
		if (camel_debug ("junk"))
			printf ("Junk classify failed with error: %s\n", error->message);
		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			g_warning ("%s: %s", G_STRFUNC, error->message);
		g_error_free (error);
		message_is_junk = FALSE;
	}

 done:
	if (camel_debug ("junk"))
		printf (
			"Message is determined to be %s\n",
			message_is_junk ? "*JUNK*" : "clean");

	r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
	r->value.number = message_is_junk;

	return r;
}