aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog18
-rw-r--r--camel/camel-mime-message.c171
-rw-r--r--camel/camel-mime-message.h5
-rw-r--r--camel/providers/smtp/camel-smtp-transport.c39
4 files changed, 221 insertions, 12 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 36fe81a875..924c5681f1 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,23 @@
2000-10-02 Jeffrey Stedfast <fejj@helixcode.com>
+ * camel-mime-message.c (camel_mime_message_has_8bit_parts): New
+ convenience function to determine if there are any 8bit mime parts
+ in a mime message.
+ (camel_mime_message_encode_8bit_parts): New convenience function
+ to recursively reencode all 8bit mime parts to either
+ quoted-printable or base64 depending on which would be the best
+ encoding for that part.
+
+ * providers/smtp/camel-smtp-transport.c (smtp_data): If the mime
+ message contains 8bit parts and the server doesn't support 8bit
+ transfers, reencode those parts before proceding with the send.
+ (smtp_mail): If the mime message contains 8bit parts and the
+ server supports the 8BITMIME extension to SMTP, notify the server
+ that we'll be sending it 8bit mime parts.
+ (_send_to): Find out if the message contains 8bit parts.
+
+2000-10-02 Jeffrey Stedfast <fejj@helixcode.com>
+
* providers/smtp/camel-smtp-transport.c (_send_to): Use the
CamelInternetAddress parser.
(smtp_get_email_addr_from_text): deprecated.
diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c
index b6bd93864e..2cb6fed5a7 100644
--- a/camel/camel-mime-message.c
+++ b/camel/camel-mime-message.c
@@ -25,11 +25,14 @@
*/
#include <config.h>
+
#include "camel-mime-message.h"
-#include <stdio.h>
+#include "camel-multipart.h"
#include "gmime-content-field.h"
+#include "camel-stream-mem.h"
#include "string-utils.h"
#include "hash-table-utils.h"
+#include <stdio.h>
#define d(x)
@@ -548,3 +551,169 @@ remove_header(CamelMedium *medium, const char *header_name)
process_header(medium, header_name, NULL);
parent_class->parent_class.remove_header (medium, header_name);
}
+
+static gboolean
+multipart_has_8bit_parts (CamelMultipart *multipart)
+{
+ gboolean has_8bit = FALSE;
+ int i, nparts;
+
+ nparts = camel_multipart_get_number (multipart);
+
+ for (i = 0; i < nparts && !has_8bit; i++) {
+ GMimeContentField *content;
+ CamelMimePart *mime_part;
+
+ mime_part = camel_multipart_get_part (multipart, i);
+ content = camel_mime_part_get_content_type (mime_part);
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ CamelDataWrapper *wrapper;
+ CamelMultipart *mpart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ mpart = CAMEL_MULTIPART (wrapper);
+
+ has_8bit = multipart_has_8bit_parts (mpart);
+ } else {
+ /* see if this part is 8bit */
+ has_8bit = camel_mime_part_get_encoding (mime_part) == CAMEL_MIME_PART_ENCODING_8BIT;
+ }
+ }
+
+ return has_8bit;
+}
+
+gboolean
+camel_mime_message_has_8bit_parts (CamelMimeMessage *mime_message)
+{
+ GMimeContentField *content;
+ gboolean has_8bit = FALSE;
+
+ content = camel_mime_part_get_content_type (CAMEL_MIME_PART (mime_message));
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ CamelDataWrapper *wrapper;
+ CamelMultipart *multipart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (mime_message)));
+ multipart = CAMEL_MULTIPART (wrapper);
+
+ has_8bit = multipart_has_8bit_parts (multipart);
+ } else {
+ /* single-part message so just check this part */
+ has_8bit = camel_mime_part_get_encoding (CAMEL_MIME_PART (mime_message)) == CAMEL_MIME_PART_ENCODING_8BIT;
+ }
+
+ return has_8bit;
+}
+
+static int
+best_encoding (const guchar *text)
+{
+ guchar *ch;
+ int count = 0;
+ int total;
+
+ for (ch = (guchar *) text; *ch; ch++)
+ if (*ch > (guchar) 127)
+ count++;
+
+ total = (int) (ch - text);
+
+ if ((float) count <= total * 0.17)
+ return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE;
+ else
+ return CAMEL_MIME_PART_ENCODING_BASE64;
+}
+
+static void
+multipart_encode_8bit_parts (CamelMultipart *multipart)
+{
+ int i, nparts;
+
+ nparts = camel_multipart_get_number (multipart);
+
+ for (i = 0; i < nparts; i++) {
+ GMimeContentField *content;
+ CamelMimePart *mime_part;
+
+ mime_part = camel_multipart_get_part (multipart, i);
+ content = camel_mime_part_get_content_type (mime_part);
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ /* ...and the search for Spock continues */
+ CamelDataWrapper *wrapper;
+ CamelMultipart *mpart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ mpart = CAMEL_MULTIPART (wrapper);
+
+ multipart_encode_8bit_parts (mpart);
+ } else {
+ /* re-encode this if necessary */
+ gboolean is_8bit;
+
+ is_8bit = camel_mime_part_get_encoding (mime_part) == CAMEL_MIME_PART_ENCODING_8BIT;
+ if (is_8bit) {
+ CamelStream *stream;
+ GByteArray *array;
+ guchar *content;
+
+ array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (array);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_part), stream);
+ g_byte_array_append (array, "", 1);
+
+ content = array->data;
+ g_byte_array_free (array, FALSE);
+
+ camel_mime_part_set_encoding (mime_part, best_encoding (content));
+ g_free (content);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ }
+ }
+ }
+}
+
+void
+camel_mime_message_encode_8bit_parts (CamelMimeMessage *mime_message)
+{
+ GMimeContentField *content;
+
+ content = camel_mime_part_get_content_type (CAMEL_MIME_PART (mime_message));
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ /* search for Spock */
+ CamelDataWrapper *wrapper;
+ CamelMultipart *multipart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (mime_message)));
+ multipart = CAMEL_MULTIPART (wrapper);
+
+ multipart_encode_8bit_parts (multipart);
+ } else {
+ /* re-encode if we need to */
+ gboolean is_8bit;
+
+ is_8bit = camel_mime_part_get_encoding (CAMEL_MIME_PART (mime_message)) == CAMEL_MIME_PART_ENCODING_8BIT;
+ if (is_8bit) {
+ /* FIXME: is there a better way of doing this? */
+ CamelStream *stream;
+ GByteArray *array;
+ guchar *content;
+
+ array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (array);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (CAMEL_MIME_PART (mime_message)), stream);
+ g_byte_array_append (array, "", 1);
+
+ content = array->data;
+ g_byte_array_free (array, FALSE);
+
+ camel_mime_part_set_encoding (CAMEL_MIME_PART (mime_message), best_encoding (content));
+ g_free (content);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ }
+ }
+}
diff --git a/camel/camel-mime-message.h b/camel/camel-mime-message.h
index 7e90d7cbcc..33436c6dad 100644
--- a/camel/camel-mime-message.h
+++ b/camel/camel-mime-message.h
@@ -111,6 +111,11 @@ void camel_mime_message_remove_recipient_name (CamelMimeMessage *mime_message,
const CamelInternetAddress *camel_mime_message_get_recipients (CamelMimeMessage *mime_message,
const char *type);
+
+/* utility functions */
+gboolean camel_mime_message_has_8bit_parts (CamelMimeMessage *mime_message);
+void camel_mime_message_encode_8bit_parts (CamelMimeMessage *mime_message);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index 02a0198f2f..2aae484c88 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -70,9 +70,11 @@ static void free_auth_types (CamelService *service, GList *authtypes);
static char *get_name (CamelService *service, gboolean brief);
static gboolean smtp_helo (CamelSmtpTransport *transport, CamelException *ex);
-static gboolean smtp_mail (CamelSmtpTransport *transport, const char *sender, CamelException *ex);
+static gboolean smtp_mail (CamelSmtpTransport *transport, const char *sender,
+ gboolean has_8bit_parts, CamelException *ex);
static gboolean smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException *ex);
-static gboolean smtp_data (CamelSmtpTransport *transport, CamelMedium *message, CamelException *ex);
+static gboolean smtp_data (CamelSmtpTransport *transport, CamelMedium *message,
+ gboolean has_8bit_parts, CamelException *ex);
static gboolean smtp_rset (CamelSmtpTransport *transport, CamelException *ex);
static gboolean smtp_quit (CamelSmtpTransport *transport, CamelException *ex);
@@ -350,6 +352,7 @@ _send_to (CamelTransport *transport, CamelMedium *message,
CamelInternetAddress *cia;
char *recipient, *sender;
const char *addr;
+ gboolean has_8bit_parts;
GList *r;
sender = g_strdup (camel_mime_message_get_from (CAMEL_MIME_MESSAGE (message)));
@@ -371,7 +374,12 @@ _send_to (CamelTransport *transport, CamelMedium *message,
return FALSE;
}
- smtp_mail (smtp_transport, addr, ex);
+ /* find out if the message has 8bit mime parts */
+ has_8bit_parts = camel_mime_message_has_8bit_parts (CAMEL_MIME_MESSAGE (message));
+
+ /* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that
+ you'll be sending an 8bit mime message at "MAIL FROM:" time. */
+ smtp_mail (smtp_transport, addr, has_8bit_parts, ex);
if (!recipients) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
@@ -389,7 +397,10 @@ _send_to (CamelTransport *transport, CamelMedium *message,
g_free (recipient);
}
- if (!smtp_data (smtp_transport, message, ex))
+ /* passing in has_8bit_parts saves time as we don't have to
+ recurse through the message all over again if the user is
+ not sending 8bit mime parts */
+ if (!smtp_data (smtp_transport, message, has_8bit_parts, ex))
return FALSE;
/* reset the service for our next transfer session */
@@ -507,13 +518,16 @@ smtp_helo (CamelSmtpTransport *transport, CamelException *ex)
}
static gboolean
-smtp_mail (CamelSmtpTransport *transport, const char *sender, CamelException *ex)
+smtp_mail (CamelSmtpTransport *transport, const char *sender, gboolean has_8bit_parts, CamelException *ex)
{
/* we gotta tell the smtp server who we are. (our email addy) */
gchar *cmdbuf, *respbuf = NULL;
/* enclose address in <>'s since some SMTP daemons *require* that */
- cmdbuf = g_strdup_printf ("MAIL FROM: <%s>\r\n", sender);
+ if (CAMEL_TRANSPORT (transport)->supports_8bit && has_8bit_parts)
+ cmdbuf = g_strdup_printf ("MAIL FROM: <%s> BODY=8BITMIME\r\n", sender);
+ else
+ cmdbuf = g_strdup_printf ("MAIL FROM: <%s>\r\n", sender);
d(fprintf (stderr, "sending : %s", cmdbuf));
@@ -591,11 +605,8 @@ smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException
return TRUE;
}
-/* FIXME: if the message has 8bit mime parts and the server doesn't
- support 8bit, we should re-encode those parts to either QP or
- Base64 */
static gboolean
-smtp_data (CamelSmtpTransport *transport, CamelMedium *message, CamelException *ex)
+smtp_data (CamelSmtpTransport *transport, CamelMedium *message, gboolean has_8bit_parts, CamelException *ex)
{
/* now we can actually send what's important :p */
gchar *cmdbuf, *respbuf = NULL;
@@ -603,7 +614,13 @@ smtp_data (CamelSmtpTransport *transport, CamelMedium *message, CamelException *
CamelMimeFilter *crlffilter, *lwfilter;
gint crlfid, lwid;
- /* enclose address in <>'s since some SMTP daemons *require* that */
+
+ /* if the message contains 8bit mime parts and the server
+ doesn't support it, encode 8bit parts to the best
+ encoding. */
+ if (has_8bit_parts && !CAMEL_TRANSPORT (transport)->supports_8bit)
+ camel_mime_message_encode_8bit_parts (CAMEL_MIME_MESSAGE (message));
+
cmdbuf = g_strdup ("DATA\r\n");
d(fprintf (stderr, "sending : %s", cmdbuf));