CamelMimeMessage * test_message_create_simple (void) { CamelMimeMessage *msg; CamelInternetAddress *addr; msg = camel_mime_message_new (); addr = camel_internet_address_new (); camel_internet_address_add (addr, "Michael Zucchi", "*****@*****.**"); camel_mime_message_set_from (msg, addr); camel_address_remove ((CamelAddress *) addr, -1); camel_internet_address_add (addr, "POSTMASTER", "*****@*****.**"); camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, addr); camel_address_remove ((CamelAddress *) addr, -1); camel_internet_address_add (addr, "Michael Zucchi", "*****@*****.**"); camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, addr); check_unref (addr, 1); camel_mime_message_set_subject (msg, "Simple message subject"); camel_mime_message_set_date (msg, time (0), 930); return msg; }
static GByteArray * anon_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) { CamelSaslAnonymous *sasl_anon = CAMEL_SASL_ANONYMOUS (sasl); CamelInternetAddress *cia; GByteArray *ret = NULL; if (token) { camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Authentication failed.")); return NULL; } switch (sasl_anon->type) { case CAMEL_SASL_ANON_TRACE_EMAIL: cia = camel_internet_address_new (); if (camel_internet_address_add (cia, NULL, sasl_anon->trace_info) != 1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Invalid email address trace information:\n%s"), sasl_anon->trace_info); camel_object_unref (cia); return NULL; } camel_object_unref (cia); ret = g_byte_array_new (); g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_OPAQUE: if (strchr (sasl_anon->trace_info, '@')) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Invalid opaque trace information:\n%s"), sasl_anon->trace_info); return NULL; } ret = g_byte_array_new (); g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_EMPTY: ret = g_byte_array_new (); break; default: camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Invalid trace information:\n%s"), sasl_anon->trace_info); return NULL; } sasl->authenticated = TRUE; return ret; }
static void check_address_line_decode (gint i, const gchar *line, const gchar *name, const gchar *email) { CamelInternetAddress *addr; const gchar *dname, *demail; push ("Testing address line %d '%s'", i, line); dname = NULL; demail = NULL; addr = camel_internet_address_new (); check (camel_address_decode (CAMEL_ADDRESS (addr), line) == 1); check (camel_internet_address_get (CAMEL_INTERNET_ADDRESS (addr), 0, &dname, &demail)); check_msg (g_strcmp0 (dname, name) == 0 || (!name && dname && !*dname), "decoded name = '%s', but should be '%s'", dname, name); check_msg (g_strcmp0 (demail, email) == 0, "decoded email = '%s', but should be '%s'", demail, email); check_unref (addr, 1); pull (); }
/* Expands groups to individual addresses, or removes empty groups completely. * Usual email addresses are left untouched. */ void em_utils_expand_groups (CamelInternetAddress *addresses) { gint ii, len; const gchar *addr; CamelAddress *addrs; g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (addresses)); addrs = CAMEL_ADDRESS (addresses); len = camel_address_length (addrs); for (ii = len - 1; ii >= 0; ii--) { addr = NULL; if (!camel_internet_address_get (addresses, ii, NULL, &addr)) { camel_address_remove (addrs, ii); } else if (addr) { gchar *encoded = camel_internet_address_encode_address (NULL, NULL, addr); if (encoded) { CamelInternetAddress *iaddr = camel_internet_address_new (); gint decoded; /* decode expands respective groups */ decoded = camel_address_decode (CAMEL_ADDRESS (iaddr), encoded); if (decoded <= 0 || decoded > 1) { camel_address_remove (addrs, ii); if (decoded > 1) camel_address_cat (addrs, CAMEL_ADDRESS (iaddr)); } g_object_unref (iaddr); g_free (encoded); } } } }
static void mail_send_short_to_thread (GSimpleAsyncResult *simple, EMailSession *session, GCancellable *cancellable) { SendAsyncContext *context; CamelFolder *local_sent_folder; CamelProvider *provider; CamelService *service; CamelInternetAddress *cia; const gchar *addr; gint i, len; gboolean copy_to_sent = TRUE; GError *error = NULL; gboolean success = FALSE; gboolean did_connect = FALSE; gboolean cancelled = FALSE; context = g_simple_async_result_get_op_res_gpointer (simple); /* Connect transport service */ service = context->transport; if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTED) { did_connect = TRUE; if (!camel_service_connect_sync (service, &error)) { mail_send_short_connection_fail (context); g_simple_async_result_take_error (simple, error); return; } } provider = camel_service_get_provider (service); if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER) copy_to_sent = FALSE; /* Send the message to each individual recipient. */ len = camel_address_length (context->recipients); for (i = 0; i < len; i++) { if (!cancelled) { if (!camel_internet_address_get( CAMEL_INTERNET_ADDRESS(context->recipients), i, NULL, &addr)) continue; cia = camel_internet_address_new (); camel_internet_address_add (cia, NULL, addr); camel_transport_send_to_sync ( CAMEL_TRANSPORT (service), context->message, context->from, CAMEL_ADDRESS(cia), cancellable, &error); g_object_unref(cia); } if (error) { g_variant_builder_add (context->result, "(sssi)", addr, error->message, g_quark_to_string(error->domain), error->code); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) cancelled = TRUE; else g_clear_error (&error); } else { g_variant_builder_add (context->result, "(sssi)", addr, "", "", 0); success = TRUE; } camel_operation_progress (cancellable, (i+1)*100/len); } g_clear_error (&error); if (did_connect) camel_service_disconnect_sync (service, FALSE, NULL); /*** Post Processing ***/ if (!success) { g_simple_async_result_set_error ( simple, E_MAIL_ERROR, E_MAIL_ERROR_POST_PROCESSING, _("All recipients failed")); return; } /* Run filters on the outgoing message. */ if (context->driver != NULL) { camel_filter_driver_filter_message ( context->driver, context->message, context->info, NULL, NULL, NULL, "", cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; g_clear_error (&error); } if (!copy_to_sent) goto cleanup; /* Append the sent message to a Sent folder. */ local_sent_folder = e_mail_session_get_local_folder (session, E_MAIL_LOCAL_FOLDER_SENT); /* Try to extract a CamelFolder from the Sent folder URI. */ if (context->sent_folder_uri != NULL) { context->sent_folder = e_mail_session_uri_to_folder_sync ( session, context->sent_folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (context->sent_folder == NULL); g_clear_error (&error); } } /* Fall back to the local Sent folder. */ if (context->sent_folder == NULL) context->sent_folder = g_object_ref (local_sent_folder); /* Append the message. */ camel_folder_append_message_sync ( context->sent_folder, context->message, context->info, NULL, cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error == NULL) goto cleanup; /* If appending to a remote Sent folder failed, * try appending to the local Sent folder. */ if (context->sent_folder != local_sent_folder) { g_clear_error (&error); camel_folder_append_message_sync (local_sent_folder, context->message, context->info, NULL, cancellable, &error); } if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; /* We can't even append to the local Sent folder? * In that case just leave the message in Outbox. */ if (error != NULL) { g_clear_error (&error); goto exit; } cleanup: /* The send operation was successful; ignore cleanup errors. */ /* Mark the draft message for deletion, if present. */ e_mail_session_handle_draft_headers_sync (session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } /* Set flags on the original source message, if present. * Source message refers to the message being forwarded * or replied to. */ e_mail_session_handle_source_headers_sync (session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } exit: /* If we were cancelled, disregard any other errors. */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_simple_async_result_take_error (simple, error); /* Stuff the accumulated error messages in a GError. */ } else if (error != NULL) { g_simple_async_result_set_error (simple, E_MAIL_ERROR, E_MAIL_ERROR_POST_PROCESSING, "%s", error->message); } /* Synchronize the Sent folder. */ if (context->sent_folder != NULL) camel_folder_synchronize_sync (context->sent_folder, FALSE, cancellable, 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; }
static GByteArray * sasl_anonymous_challenge_sync (CamelSasl *sasl, GByteArray *token, GCancellable *cancellable, GError **error) { CamelSaslAnonymous *sasl_anon = CAMEL_SASL_ANONYMOUS (sasl); CamelInternetAddress *cia; GByteArray *ret = NULL; if (token) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Authentication failed.")); return NULL; } switch (sasl_anon->type) { case CAMEL_SASL_ANON_TRACE_EMAIL: cia = camel_internet_address_new (); if (camel_internet_address_add (cia, NULL, sasl_anon->trace_info) != 1) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Invalid email address trace information:\n%s"), sasl_anon->trace_info); g_object_unref (cia); return NULL; } g_object_unref (cia); ret = g_byte_array_new (); g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_OPAQUE: if (strchr (sasl_anon->trace_info, '@')) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Invalid opaque trace information:\n%s"), sasl_anon->trace_info); return NULL; } ret = g_byte_array_new (); g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info)); break; case CAMEL_SASL_ANON_TRACE_EMPTY: ret = g_byte_array_new (); break; default: g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Invalid trace information:\n%s"), sasl_anon->trace_info); return NULL; } camel_sasl_set_authenticated (sasl, TRUE); return ret; }
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); }
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; EAccount *account = NULL; GPtrArray *post_to_uris; struct _camel_header_raw *xev; struct _camel_header_raw *header; const gchar *string; const gchar *resent_from; gchar *transport_uid = NULL; gchar *sent_folder_uri = NULL; 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); xev = mail_tool_remove_xevolution_headers (message); /* Extract directives from X-Evolution headers. */ string = camel_header_raw_find (&xev, "X-Evolution-Account", NULL); if (string != NULL) { gchar *account_uid; account_uid = g_strstrip (g_strdup (string)); account = e_get_account_by_uid (account_uid); g_free (account_uid); } if (account != NULL) { if (account->transport != NULL) { /* XXX Transport UIDs are kludgy right now. We * use the EAccount's regular UID and tack on * "-transport". Will be better soon. */ transport_uid = g_strconcat ( account->uid, "-transport", NULL); /* to reprompt password on sending if needed */ account->transport->get_password_canceled = FALSE; } sent_folder_uri = g_strdup (account->sent_folder_uri); } string = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL); if (sent_folder_uri == NULL && string != NULL) sent_folder_uri = g_strstrip (g_strdup (string)); string = camel_header_raw_find (&xev, "X-Evolution-Transport", NULL); if (transport_uid == NULL && string != NULL) transport_uid = g_strstrip (g_strdup (string)); 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 (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); /* 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->message = g_object_ref (message); context->info = info; context->xev = xev; context->post_to_uris = post_to_uris; context->transport_uid = transport_uid; context->sent_folder_uri = sent_folder_uri; 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_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); }
gint main (gint argc, gchar **argv) { gint i; CamelInternetAddress *addr, *addr2; gchar *name; const gchar *charset; const gchar *real, *where; gchar *enc, *enc2, *format, *format2; camel_test_init (argc, argv); camel_test_start ("CamelInternetAddress, basics"); addr = camel_internet_address_new (); push ("Test blank address"); check (camel_address_length (CAMEL_ADDRESS (addr)) == 0); check (camel_internet_address_get (addr, 0, &real, &where) == FALSE); pull (); push ("Test blank clone"); addr2 = CAMEL_INTERNET_ADDRESS (camel_address_new_clone (CAMEL_ADDRESS (addr))); test_address_compare (addr, addr2); check_unref (addr2, 1); pull (); push ("Test add 1"); camel_internet_address_add (addr, "Zed", "*****@*****.**"); check (camel_address_length (CAMEL_ADDRESS (addr)) == 1); check (camel_internet_address_get (addr, 0, &real, &where) == TRUE); check_msg (string_equal ("Zed", real), "real = '%s'", real); check (strcmp (where, "*****@*****.**") == 0); pull (); push ("Test clone 1"); addr2 = CAMEL_INTERNET_ADDRESS (camel_address_new_clone (CAMEL_ADDRESS (addr))); test_address_compare (addr, addr2); check_unref (addr2, 1); pull (); push ("Test add many"); for (i = 1; i < 10; i++) { gchar name[16], a[32]; sprintf (name, "Zed %d", i); sprintf (a, "nowhere@here-%d.com.au", i); camel_internet_address_add (addr, name, a); check (camel_address_length (CAMEL_ADDRESS (addr)) == i + 1); check (camel_internet_address_get (addr, i, &real, &where) == TRUE); check_msg (string_equal (name, real), "name = '%s' real = '%s'", name, real); check (strcmp (where, a) == 0); } pull (); /* put a few of these in to make it look like its doing something impressive ... :) */ camel_test_end (); camel_test_start ("CamelInternetAddress, search"); push ("Test search"); camel_test_nonfatal ("Address comparisons should ignore whitespace??"); check (camel_internet_address_find_name (addr, "Zed 1", &where) == 1); check (camel_internet_address_find_name (addr, "Zed 9", &where) == 9); check (camel_internet_address_find_name (addr, "Zed", &where) == 0); check (camel_internet_address_find_name (addr, " Zed", &where) == 0); check (camel_internet_address_find_name (addr, "Zed ", &where) == 0); check (camel_internet_address_find_name (addr, " Zed ", &where) == 0); check (camel_internet_address_find_name (addr, "Zed 20", &where) == -1); check (camel_internet_address_find_name (addr, "", &where) == -1); /* interface dont handle nulls :) */ /*check(camel_internet_address_find_name(addr, NULL, &where) == -1);*/ check (camel_internet_address_find_address (addr, "*****@*****.**", &where) == 1); check (camel_internet_address_find_address (addr, "nowhere@here-1 . com.au", &where) == 1); check (camel_internet_address_find_address (addr, "nowhere@here-2 .com.au ", &where) == 2); check (camel_internet_address_find_address (addr, " nowhere @here-3.com.au", &where) == 3); check (camel_internet_address_find_address (addr, "[email protected] ", &where) == -1); check (camel_internet_address_find_address (addr, "", &where) == -1); /*check(camel_internet_address_find_address(addr, NULL, &where) == -1);*/ camel_test_fatal (); pull (); camel_test_end (); camel_test_start ("CamelInternetAddress, copy/cat/clone"); push ("Test clone many"); addr2 = CAMEL_INTERNET_ADDRESS (camel_address_new_clone (CAMEL_ADDRESS (addr))); test_address_compare (addr, addr2); pull (); push ("Test remove items"); camel_address_remove (CAMEL_ADDRESS (addr2), 0); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 9); camel_address_remove (CAMEL_ADDRESS (addr2), 0); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 8); camel_address_remove (CAMEL_ADDRESS (addr2), 5); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 7); camel_address_remove (CAMEL_ADDRESS (addr2), 10); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 7); camel_address_remove (CAMEL_ADDRESS (addr2), -1); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 0); check_unref (addr2, 1); pull (); push ("Testing copy/cat"); push ("clone + cat"); addr2 = CAMEL_INTERNET_ADDRESS (camel_address_new_clone (CAMEL_ADDRESS (addr))); camel_address_cat (CAMEL_ADDRESS (addr2), CAMEL_ADDRESS (addr)); check (camel_address_length (CAMEL_ADDRESS (addr)) == 10); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 20); check_unref (addr2, 1); pull (); push ("cat + cat + copy"); addr2 = camel_internet_address_new (); camel_address_cat (CAMEL_ADDRESS (addr2), CAMEL_ADDRESS (addr)); test_address_compare (addr, addr2); camel_address_cat (CAMEL_ADDRESS (addr2), CAMEL_ADDRESS (addr)); check (camel_address_length (CAMEL_ADDRESS (addr)) == 10); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 20); camel_address_copy (CAMEL_ADDRESS (addr2), CAMEL_ADDRESS (addr)); test_address_compare (addr, addr2); check_unref (addr2, 1); pull (); push ("copy"); addr2 = camel_internet_address_new (); camel_address_copy (CAMEL_ADDRESS (addr2), CAMEL_ADDRESS (addr)); test_address_compare (addr, addr2); check_unref (addr2, 1); pull (); pull (); check_unref (addr, 1); camel_test_end (); camel_test_start ("CamelInternetAddress, I18N"); for (i = 0; i < G_N_ELEMENTS (test_lines); i++) { push ("Testing text line %d (%s) '%s'", i, test_lines[i].type, test_lines[i].line); addr = camel_internet_address_new (); /* first, convert to api format (utf-8) */ charset = test_lines[i].type; name = to_utf8 (test_lines[i].line, charset); push ("Address setup"); camel_internet_address_add (addr, name, "*****@*****.**"); check (camel_internet_address_get (addr, 0, &real, &where) == TRUE); check_msg (string_equal (name, real), "name = '%s' real = '%s'", name, real); check (strcmp (where, "*****@*****.**") == 0); test_free (name); check (camel_internet_address_get (addr, 1, &real, &where) == FALSE); check (camel_address_length (CAMEL_ADDRESS (addr)) == 1); pull (); push ("Address encode/decode"); enc = camel_address_encode (CAMEL_ADDRESS (addr)); addr2 = camel_internet_address_new (); check (camel_address_decode (CAMEL_ADDRESS (addr2), enc) == 1); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 1); enc2 = camel_address_encode (CAMEL_ADDRESS (addr2)); check_msg (string_equal (enc, enc2), "enc = '%s' enc2 = '%s'", enc, enc2); test_free (enc2); push ("Compare addresses"); test_address_compare (addr, addr2); pull (); check_unref (addr2, 1); test_free (enc); pull (); /* FIXME: format/unformat arne't guaranteed to be reversible, at least at the moment */ camel_test_nonfatal ("format/unformat not (yet) reversible for all cases"); push ("Address format/unformat"); format = camel_address_format (CAMEL_ADDRESS (addr)); addr2 = camel_internet_address_new (); check (camel_address_unformat (CAMEL_ADDRESS (addr2), format) == 1); check (camel_address_length (CAMEL_ADDRESS (addr2)) == 1); format2 = camel_address_format (CAMEL_ADDRESS (addr2)); check_msg (string_equal (format, format2), "format = '%s\n\tformat2 = '%s'", format, format2); test_free (format2); /* currently format/unformat doesn't handle ,'s and other special chars at all */ if (camel_address_length (CAMEL_ADDRESS (addr2)) == 1) { push ("Compare addresses"); test_address_compare (addr, addr2); pull (); } test_free (format); pull (); camel_test_fatal (); check_unref (addr2, 1); check_unref (addr, 1); pull (); } camel_test_end (); camel_test_start ("CamelInternetAddress, I18N decode"); for (i = 0; i < G_N_ELEMENTS (test_address); i++) { push ("Testing address line %d '%s'", i, test_address[i].addr); addr = camel_internet_address_new (); push ("checking decoded"); check (camel_address_decode (CAMEL_ADDRESS (addr), test_address[i].addr) == test_address[i].count); format = camel_address_format (CAMEL_ADDRESS (addr)); check (strcmp (format, test_address[i].utf8) == 0); test_free (format); pull (); push ("Comparing re-encoded output"); addr2 = CAMEL_INTERNET_ADDRESS (camel_internet_address_new ()); enc = camel_address_encode (CAMEL_ADDRESS (addr)); check_msg (camel_address_decode (CAMEL_ADDRESS (addr2), enc) == test_address[i].count, "enc = '%s'", enc); test_free (enc); test_address_compare (addr, addr2); check_unref (addr2, 1); pull (); check_unref (addr, 1); pull (); } camel_test_end (); camel_test_start ("CamelInternerAddress name & email decoder"); for (i = 0; i < G_N_ELEMENTS (test_decode); i++) { gchar *line; const gchar *name, *email; gint jj; name = test_decode[i].name; email = test_decode[i].email; for (jj = 0; jj < G_N_ELEMENTS (line_decode_formats); jj++) { if (line_decode_formats[jj].without_name) { line = g_strdup_printf (line_decode_formats[jj].without_name, email); check_address_line_decode (i, line, NULL, email); g_free (line); } if (!name) continue; line = g_strdup_printf (line_decode_formats[jj].with_name, name, email); check_address_line_decode (i, line, name, email); g_free (line); } } camel_test_end (); return 0; }
/* FIXME: check format of fields. */ static gboolean process_header (CamelMedium *medium, const gchar *name, const gchar *value) { CamelHeaderType header_type; CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium); CamelInternetAddress *addr; const gchar *charset; gchar *unfolded; header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, name); switch (header_type) { case HEADER_FROM: addr = camel_internet_address_new (); unfolded = camel_header_unfold (value); if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) { g_object_unref (addr); } else { if (message->from) g_object_unref (message->from); message->from = addr; } g_free (unfolded); break; case HEADER_REPLY_TO: addr = camel_internet_address_new (); unfolded = camel_header_unfold (value); if (camel_address_decode ((CamelAddress *) addr, unfolded) <= 0) { g_object_unref (addr); } else { if (message->reply_to) g_object_unref (message->reply_to); message->reply_to = addr; } g_free (unfolded); break; case HEADER_SUBJECT: g_free (message->subject); if (((CamelDataWrapper *) message)->mime_type) { charset = camel_content_type_param (((CamelDataWrapper *) message)->mime_type, "charset"); charset = camel_iconv_charset_name (charset); } else charset = NULL; unfolded = camel_header_unfold (value); message->subject = g_strstrip (camel_header_decode_string (unfolded, charset)); g_free (unfolded); break; case HEADER_TO: case HEADER_CC: case HEADER_BCC: case HEADER_RESENT_TO: case HEADER_RESENT_CC: case HEADER_RESENT_BCC: addr = g_hash_table_lookup (message->recipients, name); if (value) { unfolded = camel_header_unfold (value); camel_address_decode (CAMEL_ADDRESS (addr), unfolded); g_free (unfolded); } else { camel_address_remove (CAMEL_ADDRESS (addr), -1); } return FALSE; case HEADER_DATE: if (value) { message->date = camel_header_decode_date (value, &message->date_offset); } else { message->date = CAMEL_MESSAGE_DATE_CURRENT; message->date_offset = 0; } break; case HEADER_MESSAGE_ID: g_free (message->message_id); if (value) message->message_id = camel_header_msgid_decode (value); else message->message_id = NULL; break; default: return FALSE; } return TRUE; }
/* searhces for match inside value, if match is mixed case, hten use case-sensitive, else insensitive */ gboolean camel_search_header_match (const gchar *value, const gchar *match, camel_search_match_t how, camel_search_t type, const gchar *default_charset) { const gchar *name, *addr; const guchar *ptr; gint truth = FALSE, i; CamelInternetAddress *cia; gchar *v, *vdom, *mdom; gunichar c; ptr = (const guchar *)value; while ((c = camel_utf8_getc (&ptr)) && g_unichar_isspace (c)) value = (const gchar *)ptr; switch (type) { case CAMEL_SEARCH_TYPE_ENCODED: v = camel_header_decode_string (value, default_charset); /* FIXME: Find header charset */ truth = header_match (v, match, how); g_free (v); break; case CAMEL_SEARCH_TYPE_MLIST: /* Special mailing list old-version domain hack If one of the mailing list names doesn't have an @ in it, its old-style, so only match against the pre-domain part, which should be common */ vdom = strchr (value, '@'); mdom = strchr (match, '@'); if (mdom == NULL && vdom != NULL) { v = g_alloca (vdom-value+1); memcpy (v, value, vdom-value); v[vdom-value] = 0; value = (gchar *)v; } else if (mdom != NULL && vdom == NULL) { v = g_alloca (mdom-match+1); memcpy (v, match, mdom-match); v[mdom-match] = 0; match = (gchar *)v; } /* Falls through */ case CAMEL_SEARCH_TYPE_ASIS: truth = header_match (value, match, how); break; case CAMEL_SEARCH_TYPE_ADDRESS_ENCODED: case CAMEL_SEARCH_TYPE_ADDRESS: /* possible simple case to save some work if we can */ if (header_match (value, match, how)) return TRUE; /* Now we decode any addresses, and try asis matches on name and address parts */ cia = camel_internet_address_new (); if (type == CAMEL_SEARCH_TYPE_ADDRESS_ENCODED) camel_address_decode ((CamelAddress *)cia, value); else camel_address_unformat ((CamelAddress *)cia, value); for (i=0; !truth && camel_internet_address_get (cia, i, &name, &addr);i++) truth = (name && header_match (name, match, how)) || (addr && header_match (addr, match, how)); g_object_unref (cia); break; } return truth; }