1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-transport.c : Abstract class for an email transport */
7 * Dan Winship <danw@ximian.com>
9 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU Lesser General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
30 #include "camel-address.h"
31 #include "camel-debug.h"
32 #include "camel-mime-message.h"
33 #include "camel-transport.h"
35 #define CAMEL_TRANSPORT_GET_PRIVATE(obj) \
36 (G_TYPE_INSTANCE_GET_PRIVATE \
37 ((obj), CAMEL_TYPE_TRANSPORT, CamelTransportPrivate))
39 typedef struct _AsyncContext AsyncContext;
41 struct _CamelTransportPrivate {
42 GMutex send_lock; /* for locking send operations */
45 struct _AsyncContext {
48 CamelAddress *recipients;
49 CamelMimeMessage *message;
52 G_DEFINE_ABSTRACT_TYPE (CamelTransport, camel_transport, CAMEL_TYPE_SERVICE)
55 async_context_free (AsyncContext *async_context)
57 if (async_context->from != NULL)
58 g_object_unref (async_context->from);
60 if (async_context->recipients != NULL)
61 g_object_unref (async_context->recipients);
63 if (async_context->message != NULL)
64 g_object_unref (async_context->message);
66 g_slice_free (AsyncContext, async_context);
70 transport_finalize (GObject *object)
72 CamelTransportPrivate *priv;
74 priv = CAMEL_TRANSPORT_GET_PRIVATE (object);
76 g_mutex_clear (&priv->send_lock);
78 /* Chain up to parent's finalize() method. */
79 G_OBJECT_CLASS (camel_transport_parent_class)->finalize (object);
83 transport_send_to_thread (GSimpleAsyncResult *simple,
85 GCancellable *cancellable)
87 AsyncContext *async_context;
90 async_context = g_simple_async_result_get_op_res_gpointer (simple);
92 camel_transport_send_to_sync (
93 CAMEL_TRANSPORT (object), async_context->message,
94 async_context->from, async_context->recipients,
98 g_simple_async_result_take_error (simple, error);
102 transport_send_to (CamelTransport *transport,
103 CamelMimeMessage *message,
105 CamelAddress *recipients,
107 GCancellable *cancellable,
108 GAsyncReadyCallback callback,
111 GSimpleAsyncResult *simple;
112 AsyncContext *async_context;
114 async_context = g_slice_new0 (AsyncContext);
115 async_context->from = g_object_ref (from);
116 async_context->recipients = g_object_ref (recipients);
117 async_context->message = g_object_ref (message);
119 simple = g_simple_async_result_new (
120 G_OBJECT (transport), callback, user_data, transport_send_to);
122 g_simple_async_result_set_check_cancellable (simple, cancellable);
124 g_simple_async_result_set_op_res_gpointer (
125 simple, async_context, (GDestroyNotify) async_context_free);
127 g_simple_async_result_run_in_thread (
128 simple, transport_send_to_thread, io_priority, cancellable);
130 g_object_unref (simple);
134 transport_send_to_finish (CamelTransport *transport,
135 GAsyncResult *result,
138 GSimpleAsyncResult *simple;
140 g_return_val_if_fail (
141 g_simple_async_result_is_valid (
142 result, G_OBJECT (transport), transport_send_to), FALSE);
144 simple = G_SIMPLE_ASYNC_RESULT (result);
146 /* Assume success unless a GError is set. */
147 return !g_simple_async_result_propagate_error (simple, error);
151 camel_transport_class_init (CamelTransportClass *class)
153 GObjectClass *object_class;
155 g_type_class_add_private (class, sizeof (CamelTransportPrivate));
157 object_class = G_OBJECT_CLASS (class);
158 object_class->finalize = transport_finalize;
160 class->send_to = transport_send_to;
161 class->send_to_finish = transport_send_to_finish;
165 camel_transport_init (CamelTransport *transport)
167 transport->priv = CAMEL_TRANSPORT_GET_PRIVATE (transport);
169 g_mutex_init (&transport->priv->send_lock);
173 * camel_transport_lock:
174 * @transport: a #CamelTransport
175 * @lock: lock type to lock
177 * Locks %transport's %lock. Unlock it with camel_transport_unlock().
182 camel_transport_lock (CamelTransport *transport,
183 CamelTransportLock lock)
185 g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
188 case CAMEL_TRANSPORT_SEND_LOCK:
189 g_mutex_lock (&transport->priv->send_lock);
192 g_return_if_reached ();
197 * camel_transport_unlock:
198 * @transport: a #CamelTransport
199 * @lock: lock type to unlock
201 * Unlocks %transport's %lock, previously locked with camel_transport_lock().
206 camel_transport_unlock (CamelTransport *transport,
207 CamelTransportLock lock)
209 g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
212 case CAMEL_TRANSPORT_SEND_LOCK:
213 g_mutex_unlock (&transport->priv->send_lock);
216 g_return_if_reached ();
221 * camel_transport_send_to_sync:
222 * @transport: a #CamelTransport
223 * @message: a #CamelMimeMessage to send
224 * @from: a #CamelAddress to send from
225 * @recipients: a #CamelAddress containing all recipients
226 * @cancellable: optional #GCancellable object, or %NULL
227 * @error: return location for a #GError, or %NULL
229 * Sends the message to the given recipients, regardless of the contents
230 * of @message. If the message contains a "Bcc" header, the transport
231 * is responsible for stripping it.
233 * Returns: %TRUE on success or %FALSE on error
238 camel_transport_send_to_sync (CamelTransport *transport,
239 CamelMimeMessage *message,
241 CamelAddress *recipients,
242 GCancellable *cancellable,
245 CamelTransportClass *class;
248 g_return_val_if_fail (CAMEL_IS_TRANSPORT (transport), FALSE);
249 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
250 g_return_val_if_fail (CAMEL_IS_ADDRESS (from), FALSE);
251 g_return_val_if_fail (CAMEL_IS_ADDRESS (recipients), FALSE);
253 class = CAMEL_TRANSPORT_GET_CLASS (transport);
254 g_return_val_if_fail (class->send_to_sync != NULL, FALSE);
256 camel_transport_lock (transport, CAMEL_TRANSPORT_SEND_LOCK);
258 /* Check for cancellation after locking. */
259 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
260 camel_transport_unlock (transport, CAMEL_TRANSPORT_SEND_LOCK);
264 success = class->send_to_sync (
265 transport, message, from, recipients, cancellable, error);
266 CAMEL_CHECK_GERROR (transport, send_to_sync, success, error);
268 camel_transport_unlock (transport, CAMEL_TRANSPORT_SEND_LOCK);
274 * camel_transport_send_to:
275 * @transport: a #CamelTransport
276 * @message: a #CamelMimeMessage to send
277 * @from: a #CamelAddress to send from
278 * @recipients: a #CamelAddress containing all recipients
279 * @io_priority: the I/O priority of the request
280 * @cancellable: optional #GCancellable object, or %NULL
281 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
282 * @user_data: data to pass to the callback function
284 * Sends the message asynchronously to the given recipients, regardless of
285 * the contents of @message. If the message contains a "Bcc" header, the
286 * transport is responsible for stripping it.
288 * When the operation is finished, @callback will be called. You can then
289 * call camel_transport_send_to_finish() to get the result of the operation.
294 camel_transport_send_to (CamelTransport *transport,
295 CamelMimeMessage *message,
297 CamelAddress *recipients,
299 GCancellable *cancellable,
300 GAsyncReadyCallback callback,
303 CamelTransportClass *class;
305 g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
306 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
307 g_return_if_fail (CAMEL_IS_ADDRESS (from));
308 g_return_if_fail (CAMEL_IS_ADDRESS (recipients));
310 class = CAMEL_TRANSPORT_GET_CLASS (transport);
311 g_return_if_fail (class->send_to != NULL);
314 transport, message, from, recipients, io_priority,
315 cancellable, callback, user_data);
319 * camel_transport_send_to_finish:
320 * @transport: a #CamelTransport
321 * @result: a #GAsyncResult
322 * @error: return locaton for a #GError, or %NULL
324 * Finishes the operation started with camel_transport_send_to().
326 * Returns: %TRUE on success, %FALSE on error
331 camel_transport_send_to_finish (CamelTransport *transport,
332 GAsyncResult *result,
335 CamelTransportClass *class;
337 g_return_val_if_fail (CAMEL_IS_TRANSPORT (transport), FALSE);
338 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
340 class = CAMEL_TRANSPORT_GET_CLASS (transport);
341 g_return_val_if_fail (class->send_to_finish != NULL, FALSE);
343 return class->send_to_finish (transport, result, error);