~ubuntu-branches/ubuntu/precise/evolution-data-server/precise

« back to all changes in this revision

Viewing changes to camel/providers/smtp/camel-smtp-transport.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2011-07-27 11:45:30 UTC
  • mfrom: (1.1.90 upstream)
  • Revision ID: james.westby@ubuntu.com-20110727114530-v4ntbu728os68b0b
Tags: 3.1.4-0ubuntu1
* New upstream version.
* debian/patches/999git_EDS_3_1_3_1_to_f94a069.patch: drop, included in
  the upstream 3.1.4 tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
                                                 GError **error);
89
89
 
90
90
enum {
91
 
        MODE_CLEAR,
92
 
        MODE_SSL,
93
 
        MODE_TLS
94
 
};
95
 
 
96
 
#ifdef CAMEL_HAVE_SSL
97
 
#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3)
98
 
#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS)
99
 
#endif
100
 
 
101
 
static struct {
102
 
        const gchar *value;
103
 
        const gchar *serv;
104
 
        gint fallback_port;
105
 
        gint mode;
106
 
} ssl_options[] = {
107
 
        { "",              "smtps", SMTPS_PORT, MODE_SSL  },  /* really old (1.x) */
108
 
        { "always",        "smtps", SMTPS_PORT, MODE_SSL  },
109
 
        { "when-possible", "smtp",  SMTP_PORT, MODE_TLS   },
110
 
        { "never",         "smtp",  SMTP_PORT, MODE_CLEAR },
111
 
        { NULL,            "smtp",  SMTP_PORT, MODE_CLEAR }
112
 
};
113
 
 
114
 
G_DEFINE_TYPE (CamelSmtpTransport, camel_smtp_transport, CAMEL_TYPE_TRANSPORT)
 
91
        PROP_0,
 
92
        PROP_DEFAULT_PORT,
 
93
        PROP_SECURITY_METHOD,
 
94
        PROP_SERVICE_NAME
 
95
};
 
96
 
 
97
/* Forward Declarations */
 
98
static void camel_network_service_init (CamelNetworkServiceInterface *interface);
 
99
 
 
100
G_DEFINE_TYPE_WITH_CODE (
 
101
        CamelSmtpTransport,
 
102
        camel_smtp_transport,
 
103
        CAMEL_TYPE_TRANSPORT,
 
104
        G_IMPLEMENT_INTERFACE (
 
105
                CAMEL_TYPE_NETWORK_SERVICE,
 
106
                camel_network_service_init))
115
107
 
116
108
static gboolean
117
109
connect_to_server (CamelService *service,
118
 
                   const gchar *host,
119
 
                   const gchar *serv,
120
 
                   gint fallback_port,
121
 
                   gint ssl_mode,
122
110
                   GCancellable *cancellable,
123
111
                   GError **error)
124
112
{
125
113
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
126
 
        CamelSession *session;
 
114
        CamelNetworkService *network_service;
 
115
        CamelNetworkSecurityMethod method;
127
116
        CamelURL *url;
128
 
        gchar *socks_host;
129
 
        gint socks_port;
130
117
        CamelStream *tcp_stream;
131
118
        gchar *respbuf = NULL;
132
119
 
139
126
        transport->authtypes = NULL;
140
127
 
141
128
        url = camel_service_get_camel_url (service);
142
 
        session = camel_service_get_session (service);
143
 
 
144
 
        if (ssl_mode != MODE_CLEAR) {
145
 
#ifdef CAMEL_HAVE_SSL
146
 
                if (ssl_mode == MODE_TLS) {
147
 
                        tcp_stream = camel_tcp_stream_ssl_new_raw (session, url->host, STARTTLS_FLAGS);
148
 
                } else {
149
 
                        tcp_stream = camel_tcp_stream_ssl_new (session, url->host, SSL_PORT_FLAGS);
150
 
                }
151
 
#else
152
 
                g_set_error (
153
 
                        error, CAMEL_SERVICE_ERROR,
154
 
                        CAMEL_SERVICE_ERROR_UNAVAILABLE,
155
 
                        _("Could not connect to %s: %s"),
156
 
                        url->host, _("SSL unavailable"));
157
 
 
158
 
                return FALSE;
159
 
#endif /* CAMEL_HAVE_SSL */
160
 
        } else {
161
 
                tcp_stream = camel_tcp_stream_raw_new ();
162
 
        }
163
 
 
164
 
        camel_session_get_socks_proxy (session, &socks_host, &socks_port);
165
 
 
166
 
        if (socks_host) {
167
 
                camel_tcp_stream_set_socks_proxy (
168
 
                        CAMEL_TCP_STREAM (tcp_stream),
169
 
                        socks_host, socks_port);
170
 
                g_free (socks_host);
171
 
        }
172
 
 
173
 
        if (camel_tcp_stream_connect (
174
 
                CAMEL_TCP_STREAM (tcp_stream), host, serv,
175
 
                fallback_port, cancellable, error) == -1) {
176
 
                g_object_unref (tcp_stream);
177
 
                return FALSE;
178
 
        }
 
129
 
 
130
        network_service = CAMEL_NETWORK_SERVICE (service);
 
131
        method = camel_network_service_get_security_method (network_service);
 
132
 
 
133
        tcp_stream = camel_network_service_connect_sync (
 
134
                CAMEL_NETWORK_SERVICE (service), cancellable, error);
 
135
 
 
136
        if (tcp_stream == NULL)
 
137
                return FALSE;
179
138
 
180
139
        transport->connected = TRUE;
181
140
 
228
187
        /* clear any EHLO/HELO exception and assume that any SMTP errors encountered were non-fatal */
229
188
        g_clear_error (error);
230
189
 
231
 
        if (ssl_mode != MODE_TLS) {
232
 
                /* we're done */
233
 
                return TRUE;
234
 
        }
 
190
        if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT)
 
191
                return TRUE;  /* we're done */
235
192
 
236
193
#ifdef CAMEL_HAVE_SSL
237
194
        if (!(transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS)) {
311
268
        return FALSE;
312
269
}
313
270
 
314
 
static gboolean
315
 
connect_to_server_wrapper (CamelService *service,
316
 
                           GCancellable *cancellable,
317
 
                           GError **error)
318
 
{
319
 
        CamelURL *url;
320
 
        const gchar *ssl_mode;
321
 
        gint mode, i;
322
 
        gchar *serv;
323
 
        gint fallback_port;
324
 
 
325
 
        url = camel_service_get_camel_url (service);
326
 
 
327
 
        if ((ssl_mode = camel_url_get_param (url, "use_ssl"))) {
328
 
                for (i = 0; ssl_options[i].value; i++)
329
 
                        if (!strcmp (ssl_options[i].value, ssl_mode))
330
 
                                break;
331
 
                mode = ssl_options[i].mode;
332
 
                serv = (gchar *) ssl_options[i].serv;
333
 
                fallback_port = ssl_options[i].fallback_port;
334
 
        } else {
335
 
                mode = MODE_CLEAR;
336
 
                serv = (gchar *) "smtp";
337
 
                fallback_port = SMTP_PORT;
338
 
        }
339
 
 
340
 
        if (url->port) {
341
 
                serv = g_alloca (16);
342
 
                sprintf (serv, "%d", url->port);
343
 
                fallback_port = 0;
344
 
        }
345
 
 
346
 
        return connect_to_server (
347
 
                service, url->host, serv,
348
 
                fallback_port, mode, cancellable, error);
349
 
}
350
 
 
351
271
static void
352
272
authtypes_free (gpointer key, gpointer value, gpointer data)
353
273
{
354
274
        g_free (value);
355
275
}
356
276
 
 
277
static void
 
278
smtp_transport_set_property (GObject *object,
 
279
                             guint property_id,
 
280
                             const GValue *value,
 
281
                             GParamSpec *pspec)
 
282
{
 
283
        switch (property_id) {
 
284
                case PROP_SECURITY_METHOD:
 
285
                        camel_network_service_set_security_method (
 
286
                                CAMEL_NETWORK_SERVICE (object),
 
287
                                g_value_get_enum (value));
 
288
                        return;
 
289
        }
 
290
 
 
291
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
292
}
 
293
 
 
294
static void
 
295
smtp_transport_get_property (GObject *object,
 
296
                             guint property_id,
 
297
                             GValue *value,
 
298
                             GParamSpec *pspec)
 
299
{
 
300
        switch (property_id) {
 
301
                case PROP_DEFAULT_PORT:
 
302
                        g_value_set_uint (
 
303
                                value,
 
304
                                camel_network_service_get_default_port (
 
305
                                CAMEL_NETWORK_SERVICE (object)));
 
306
                        return;
 
307
 
 
308
                case PROP_SECURITY_METHOD:
 
309
                        g_value_set_enum (
 
310
                                value,
 
311
                                camel_network_service_get_security_method (
 
312
                                CAMEL_NETWORK_SERVICE (object)));
 
313
                        return;
 
314
 
 
315
                case PROP_SERVICE_NAME:
 
316
                        g_value_set_string (
 
317
                                value,
 
318
                                camel_network_service_get_service_name (
 
319
                                CAMEL_NETWORK_SERVICE (object)));
 
320
                        return;
 
321
        }
 
322
 
 
323
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
324
}
 
325
 
 
326
static void
 
327
smtp_transport_constructed (GObject *object)
 
328
{
 
329
        CamelURL *url;
 
330
        const gchar *use_ssl;
 
331
 
 
332
        /* Chain up to parent's constructed() method. */
 
333
        G_OBJECT_CLASS (camel_smtp_transport_parent_class)->constructed (object);
 
334
 
 
335
        url = camel_service_get_camel_url (CAMEL_SERVICE (object));
 
336
        use_ssl = camel_url_get_param (url, "use_ssl");
 
337
 
 
338
        if (g_strcmp0 (use_ssl, "never") == 0)
 
339
                camel_network_service_set_security_method (
 
340
                        CAMEL_NETWORK_SERVICE (object),
 
341
                        CAMEL_NETWORK_SECURITY_METHOD_NONE);
 
342
        else if (g_strcmp0 (use_ssl, "always") == 0)
 
343
                camel_network_service_set_security_method (
 
344
                        CAMEL_NETWORK_SERVICE (object),
 
345
                        CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT);
 
346
        else if (g_strcmp0 (use_ssl, "when-possible") == 0)
 
347
                camel_network_service_set_security_method (
 
348
                        CAMEL_NETWORK_SERVICE (object),
 
349
                        CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT);
 
350
}
 
351
 
357
352
static gchar *
358
 
smtp_get_name (CamelService *service, gboolean brief)
 
353
smtp_transport_get_name (CamelService *service, gboolean brief)
359
354
{
360
355
        CamelURL *url;
361
356
 
372
367
}
373
368
 
374
369
static gboolean
375
 
smtp_connect_sync (CamelService *service,
376
 
                   GCancellable *cancellable,
377
 
                   GError **error)
 
370
smtp_transport_connect_sync (CamelService *service,
 
371
                             GCancellable *cancellable,
 
372
                             GError **error)
378
373
{
379
374
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
380
375
        CamelSasl *sasl = NULL;
399
394
                if (!truth)
400
395
                        return FALSE;
401
396
 
402
 
                return connect_to_server_wrapper (service, cancellable, error);
 
397
                return connect_to_server (service, cancellable, error);
403
398
        }
404
399
 
405
 
        if (!connect_to_server_wrapper (service, cancellable, error))
 
400
        if (!connect_to_server (service, cancellable, error))
406
401
                return FALSE;
407
402
 
408
403
        /* check to see if AUTH is required, if so...then AUTH ourselves */
536
531
}
537
532
 
538
533
static gboolean
539
 
smtp_disconnect_sync (CamelService *service,
540
 
                      gboolean clean,
541
 
                      GCancellable *cancellable,
542
 
                      GError **error)
 
534
smtp_transport_disconnect_sync (CamelService *service,
 
535
                                gboolean clean,
 
536
                                GCancellable *cancellable,
 
537
                                GError **error)
543
538
{
544
539
        CamelServiceClass *service_class;
545
540
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
583
578
}
584
579
 
585
580
static GList *
586
 
smtp_query_auth_types_sync (CamelService *service,
587
 
                            GCancellable *cancellable,
588
 
                            GError **error)
 
581
smtp_transport_query_auth_types_sync (CamelService *service,
 
582
                                      GCancellable *cancellable,
 
583
                                      GError **error)
589
584
{
590
585
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
591
586
        CamelServiceAuthType *authtype;
592
587
        CamelProvider *provider;
593
588
        GList *types, *t, *next;
594
589
 
595
 
        if (!connect_to_server_wrapper (service, cancellable, error))
 
590
        if (!connect_to_server (service, cancellable, error))
596
591
                return NULL;
597
592
 
598
593
        if (!transport->authtypes) {
599
 
                smtp_disconnect_sync (service, TRUE, cancellable, NULL);
 
594
                smtp_transport_disconnect_sync (
 
595
                        service, TRUE, cancellable, NULL);
600
596
                return NULL;
601
597
        }
602
598
 
613
609
                }
614
610
        }
615
611
 
616
 
        smtp_disconnect_sync (service, TRUE, cancellable, NULL);
 
612
        smtp_transport_disconnect_sync (service, TRUE, cancellable, NULL);
617
613
 
618
614
        return types;
619
615
}
620
616
 
621
617
static gboolean
622
 
smtp_send_to_sync (CamelTransport *transport,
623
 
                   CamelMimeMessage *message,
624
 
                   CamelAddress *from,
625
 
                   CamelAddress *recipients,
626
 
                   GCancellable *cancellable,
627
 
                   GError **error)
 
618
smtp_transport_send_to_sync (CamelTransport *transport,
 
619
                             CamelMimeMessage *message,
 
620
                             CamelAddress *from,
 
621
                             CamelAddress *recipients,
 
622
                             GCancellable *cancellable,
 
623
                             GError **error)
628
624
{
629
625
        CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (transport);
630
626
        CamelInternetAddress *cia;
713
709
        return TRUE;
714
710
}
715
711
 
 
712
static const gchar *
 
713
smtp_transport_get_service_name (CamelNetworkService *service)
 
714
{
 
715
        CamelNetworkSecurityMethod method;
 
716
        const gchar *service_name;
 
717
 
 
718
        method = camel_network_service_get_security_method (service);
 
719
 
 
720
        switch (method) {
 
721
                case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
 
722
                        service_name = "smtps";
 
723
                        break;
 
724
 
 
725
                default:
 
726
                        service_name = "smtp";
 
727
                        break;
 
728
        }
 
729
 
 
730
        return service_name;
 
731
}
 
732
 
 
733
static guint16
 
734
smtp_transport_get_default_port (CamelNetworkService *service)
 
735
{
 
736
        CamelNetworkSecurityMethod method;
 
737
        guint16 default_port;
 
738
 
 
739
        method = camel_network_service_get_security_method (service);
 
740
 
 
741
        switch (method) {
 
742
                case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
 
743
                        default_port = SMTPS_PORT;
 
744
                        break;
 
745
 
 
746
                default:
 
747
                        default_port = SMTP_PORT;
 
748
                        break;
 
749
        }
 
750
 
 
751
        return default_port;
 
752
}
 
753
 
716
754
static void
717
755
camel_smtp_transport_class_init (CamelSmtpTransportClass *class)
718
756
{
 
757
        GObjectClass *object_class;
 
758
        CamelServiceClass *service_class;
719
759
        CamelTransportClass *transport_class;
720
 
        CamelServiceClass *service_class;
 
760
 
 
761
        object_class = G_OBJECT_CLASS (class);
 
762
        object_class->set_property = smtp_transport_set_property;
 
763
        object_class->get_property = smtp_transport_get_property;
 
764
        object_class->constructed = smtp_transport_constructed;
721
765
 
722
766
        service_class = CAMEL_SERVICE_CLASS (class);
723
 
        service_class->get_name = smtp_get_name;
724
 
        service_class->connect_sync = smtp_connect_sync;
725
 
        service_class->disconnect_sync = smtp_disconnect_sync;
726
 
        service_class->query_auth_types_sync = smtp_query_auth_types_sync;
 
767
        service_class->get_name = smtp_transport_get_name;
 
768
        service_class->connect_sync = smtp_transport_connect_sync;
 
769
        service_class->disconnect_sync = smtp_transport_disconnect_sync;
 
770
        service_class->query_auth_types_sync = smtp_transport_query_auth_types_sync;
727
771
 
728
772
        transport_class = CAMEL_TRANSPORT_CLASS (class);
729
 
        transport_class->send_to_sync = smtp_send_to_sync;
 
773
        transport_class->send_to_sync = smtp_transport_send_to_sync;
 
774
 
 
775
        /* Inherited from CamelNetworkService. */
 
776
        g_object_class_override_property (
 
777
                object_class,
 
778
                PROP_DEFAULT_PORT,
 
779
                "default-port");
 
780
 
 
781
        /* Inherited from CamelNetworkService. */
 
782
        g_object_class_override_property (
 
783
                object_class,
 
784
                PROP_SECURITY_METHOD,
 
785
                "security-method");
 
786
 
 
787
        /* Inherited from CamelNetworkService. */
 
788
        g_object_class_override_property (
 
789
                object_class,
 
790
                PROP_SERVICE_NAME,
 
791
                "service-name");
 
792
}
 
793
 
 
794
static void
 
795
camel_network_service_init (CamelNetworkServiceInterface *interface)
 
796
{
 
797
        interface->get_service_name = smtp_transport_get_service_name;
 
798
        interface->get_default_port = smtp_transport_get_default_port;
730
799
}
731
800
 
732
801
static void