1 /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ 2 /* Balsa E-Mail Client 3 * Copyright (C) 1997-2013 Stuart Parmenter and others, 4 * See the file AUTHORS for a list. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22 #ifndef __LIBBALSA_MESSAGE_H__ 23 #define __LIBBALSA_MESSAGE_H__ 24 25 #ifndef BALSA_VERSION 26 # error "Include config.h before this file." 27 #endif 28 29 #include <glib.h> 30 31 #include <stdio.h> 32 #include <time.h> 33 34 #include <gmime/gmime.h> 35 36 #ifdef HAVE_GPGME 37 #include "rfc3156.h" 38 #endif 39 40 #define MESSAGE_COPY_CONTENT 1 41 #define LIBBALSA_TYPE_MESSAGE \ 42 (libbalsa_message_get_type()) 43 #define LIBBALSA_MESSAGE(obj) \ 44 (G_TYPE_CHECK_INSTANCE_CAST(obj, LIBBALSA_TYPE_MESSAGE, LibBalsaMessage)) 45 #define LIBBALSA_MESSAGE_CLASS(klass) \ 46 (G_TYPE_CHECK_CLASS_CAST(klass, LIBBALSA_TYPE_MESSAGE, \ 47 LibBalsaMessageClass)) 48 #define LIBBALSA_IS_MESSAGE(obj) \ 49 (G_TYPE_CHECK_INSTANCE_TYPE(obj, LIBBALSA_TYPE_MESSAGE)) 50 #define LIBBALSA_IS_MESSAGE_CLASS(klass) \ 51 (G_TYPE_CHECK_CLASS_TYPE(klass, LIBBALSA_TYPE_MESSAGE)) 52 53 typedef struct _LibBalsaMessageClass LibBalsaMessageClass; 54 typedef enum _LibBalsaMessageFlag LibBalsaMessageFlag; 55 56 enum _LibBalsaMessageFlag { 57 LIBBALSA_MESSAGE_FLAG_NEW = 1 << 0, 58 LIBBALSA_MESSAGE_FLAG_DELETED = 1 << 1, 59 LIBBALSA_MESSAGE_FLAG_REPLIED = 1 << 2, 60 LIBBALSA_MESSAGE_FLAG_FLAGGED = 1 << 3, 61 LIBBALSA_MESSAGE_FLAG_RECENT = 1 << 4, 62 LIBBALSA_MESSAGE_FLAG_SELECTED= 1 << 5 /* pseudo flag */ 63 }; 64 65 #define LIBBALSA_MESSAGE_FLAGS_REAL \ 66 (LIBBALSA_MESSAGE_FLAG_NEW | \ 67 LIBBALSA_MESSAGE_FLAG_DELETED | \ 68 LIBBALSA_MESSAGE_FLAG_REPLIED | \ 69 LIBBALSA_MESSAGE_FLAG_FLAGGED | \ 70 LIBBALSA_MESSAGE_FLAG_RECENT) 71 72 typedef enum _LibBalsaMessageStatus LibBalsaMessageStatus; 73 enum _LibBalsaMessageStatus { 74 LIBBALSA_MESSAGE_STATUS_UNREAD, 75 LIBBALSA_MESSAGE_STATUS_DELETED, 76 LIBBALSA_MESSAGE_STATUS_FLAGGED, 77 LIBBALSA_MESSAGE_STATUS_REPLIED, 78 LIBBALSA_MESSAGE_STATUS_ICONS_NUM 79 }; 80 81 82 #ifdef HAVE_GPGME 83 typedef enum _LibBalsaMsgProtectState LibBalsaMsgProtectState; 84 85 enum _LibBalsaMsgProtectState { 86 LIBBALSA_MSG_PROTECT_NONE, 87 LIBBALSA_MSG_PROTECT_SIGN_UNKNOWN, 88 LIBBALSA_MSG_PROTECT_SIGN_GOOD, 89 LIBBALSA_MSG_PROTECT_SIGN_NOTRUST, 90 LIBBALSA_MSG_PROTECT_SIGN_BAD, 91 LIBBALSA_MSG_PROTECT_CRYPT 92 }; 93 #endif 94 95 typedef enum _LibBalsaMessageAttach LibBalsaMessageAttach; 96 enum _LibBalsaMessageAttach { 97 LIBBALSA_MESSAGE_ATTACH_ATTACH, 98 #ifdef HAVE_GPGME 99 LIBBALSA_MESSAGE_ATTACH_GOOD, 100 LIBBALSA_MESSAGE_ATTACH_NOTRUST, 101 LIBBALSA_MESSAGE_ATTACH_BAD, 102 LIBBALSA_MESSAGE_ATTACH_SIGN, 103 LIBBALSA_MESSAGE_ATTACH_ENCR, 104 #endif 105 LIBBALSA_MESSAGE_ATTACH_ICONS_NUM 106 }; 107 108 109 /* 110 * Message info used by mailbox; 111 * 112 * headers->from 113 * headers->date 114 * headers->to_list 115 * headers->content_type 116 * subj 117 * length 118 * lines_len (scrap?) 119 * 120 * loaded by driver: 121 * flags 122 * 123 * needed for threading local mailboxes: 124 * message_id 125 * references 126 * in_reply_to 127 */ 128 /* 129 * LibBalsaMessageHeaders contains all headers which are used to display both 130 * a "main" message's headers as well as those from an embedded message/rfc822 131 * part. 132 */ 133 struct _LibBalsaMessageHeaders { 134 /* message composition date */ 135 time_t date; 136 137 /* subject (for embedded messages only) */ 138 gchar *subject; 139 140 /* from, reply, and disposition notification addresses */ 141 InternetAddressList *from; 142 InternetAddressList *reply_to; 143 InternetAddressList *dispnotify_to; 144 145 /* primary, secondary, and blind recipent lists */ 146 InternetAddressList *to_list; 147 InternetAddressList *cc_list; 148 InternetAddressList *bcc_list; 149 150 /* Mime type */ 151 GMimeContentType *content_type; 152 153 /* File Carbon Copy Mailbox URL */ 154 gchar *fcc_url; 155 156 /* other headers */ 157 GList *user_hdrs; 158 }; 159 160 /** FREE_HEADER_LIST() frees user_hdrs */ 161 #define FREE_HEADER_LIST(l) do{ g_list_foreach((l),(GFunc)g_strfreev,NULL);\ 162 g_list_free(l); } while(0) 163 164 struct _LibBalsaMessage { 165 GObject object; 166 167 /* the mailbox this message belongs to */ 168 LibBalsaMailbox *mailbox; 169 170 /* flags */ 171 LibBalsaMessageFlag flags; 172 173 /* headers */ 174 LibBalsaMessageHeaders *headers; 175 int updated; /** whether complete headers have been fetched */ 176 177 GMimeMessage *mime_msg; 178 179 /* sender address */ 180 InternetAddressList *sender; 181 182 /* subject line; we still need it here for sending; 183 * although _SET_SUBJECT might resolve it(?) 184 * but we can set to to NULL unless there is no mailbox, like 185 * on sending. */ 186 gchar *subj; 187 #ifdef MESSAGE_COPY_CONTENT 188 #define LIBBALSA_MESSAGE_GET_SUBJECT(m) \ 189 ((m)->subj ? (m)->subj : _("(No subject)")) 190 #else 191 #define LIBBALSA_MESSAGE_GET_SUBJECT(m) libbalsa_message_get_subject(m) 192 #endif 193 194 /* replied message ID's */ 195 GList *references; 196 197 /* replied message ID; from address on date */ 198 GList *in_reply_to; 199 200 /* message ID */ 201 gchar *message_id; 202 203 #ifdef HAVE_GPGME 204 /* GPG sign and/or encrypt message (sending) */ 205 guint gpg_mode; 206 207 /* protection (i.e. sign/encrypt) status (received message) */ 208 LibBalsaMsgProtectState prot_state; 209 210 /* forced id of the senders secret key, empty to choose it from the mail address */ 211 gchar * force_key_id; 212 #endif 213 214 /* a forced multipart subtype or NULL for mixed; used only for 215 * sending */ 216 gchar *subtype; 217 218 /* additional message content type parameters; used only for sending */ 219 GList *parameters; 220 221 /* message body */ 222 guint body_ref; 223 LibBalsaMessageBody *body_list; 224 /* GList *body_list; */ 225 226 glong msgno; /* message no; always copy for faster sorting; 227 * counting starts at 1. */ 228 #if MESSAGE_COPY_CONTENT 229 #define LIBBALSA_MESSAGE_GET_NO(m) ((m)->msgno) 230 glong length; /* byte len */ 231 #define LIBBALSA_MESSAGE_GET_LENGTH(m) ((m)->length) 232 #else 233 #define LIBBALSA_MESSAGE_GET_LENGTH(m) libbalsa_message_get_length(m) 234 #define LIBBALSA_MESSAGE_GET_NO(m) libbalsa_message_get_no(m) 235 #endif 236 237 gchar *tempdir; /* to hold named parts */ 238 239 unsigned has_all_headers:1; 240 }; 241 242 #define LIBBALSA_MESSAGE_HAS_FLAG(message, mask) \ 243 ((LIBBALSA_MESSAGE(message)->flags & mask) != 0) 244 #define LIBBALSA_MESSAGE_IS_UNREAD(message) \ 245 LIBBALSA_MESSAGE_HAS_FLAG(message, LIBBALSA_MESSAGE_FLAG_NEW) 246 #define LIBBALSA_MESSAGE_IS_DELETED(message) \ 247 LIBBALSA_MESSAGE_HAS_FLAG(message, LIBBALSA_MESSAGE_FLAG_DELETED) 248 #define LIBBALSA_MESSAGE_IS_REPLIED(message) \ 249 LIBBALSA_MESSAGE_HAS_FLAG(message, LIBBALSA_MESSAGE_FLAG_REPLIED) 250 #define LIBBALSA_MESSAGE_IS_FLAGGED(message) \ 251 LIBBALSA_MESSAGE_HAS_FLAG(message, LIBBALSA_MESSAGE_FLAG_FLAGGED) 252 #define LIBBALSA_MESSAGE_IS_RECENT(message) \ 253 LIBBALSA_MESSAGE_HAS_FLAG(message, LIBBALSA_MESSAGE_FLAG_RECENT) 254 255 struct _LibBalsaMessageClass { 256 GObjectClass parent_class; 257 258 /* deal with flags being set/unset */ 259 /* Signal: */ 260 void (*status_changed) (LibBalsaMessage * message, 261 LibBalsaMessageFlag flag, gboolean); 262 }; 263 264 265 GType libbalsa_message_get_type(void); 266 267 /* 268 * message headers 269 */ 270 void libbalsa_message_headers_destroy(LibBalsaMessageHeaders * headers); 271 void libbalsa_message_headers_from_gmime(LibBalsaMessageHeaders *headers, 272 GMimeMessage *msg); 273 void libbalsa_message_init_from_gmime(LibBalsaMessage * message, 274 GMimeMessage * msg); 275 GList *libbalsa_message_user_hdrs_from_gmime(GMimeMessage *msg); 276 277 278 /* 279 * messages 280 */ 281 LibBalsaMessage *libbalsa_message_new(void); 282 283 gboolean libbalsa_message_save(LibBalsaMessage * message, 284 const gchar *filename); 285 286 void libbalsa_message_reply(LibBalsaMessage * message); 287 288 void libbalsa_message_append_part(LibBalsaMessage * message, 289 LibBalsaMessageBody * body); 290 291 gboolean libbalsa_message_body_ref(LibBalsaMessage * message, gboolean read, 292 gboolean fetch_all_headers); 293 void libbalsa_message_body_unref(LibBalsaMessage * message); 294 295 /* 296 * misc message releated functions 297 */ 298 const gchar *libbalsa_message_pathname(LibBalsaMessage * message); 299 const gchar *libbalsa_message_body_charset(LibBalsaMessageBody * body); 300 gboolean libbalsa_message_is_multipart(LibBalsaMessage * message); 301 gboolean libbalsa_message_is_partial(LibBalsaMessage * message, 302 gchar ** id); 303 gboolean libbalsa_message_has_attachment(LibBalsaMessage * message); 304 #ifdef HAVE_GPGME 305 gboolean libbalsa_message_is_pgp_signed(LibBalsaMessage * message); 306 gboolean libbalsa_message_is_pgp_encrypted(LibBalsaMessage * message); 307 #endif 308 309 const gchar* libbalsa_message_header_get_one(LibBalsaMessageHeaders* headers, 310 const gchar *find); 311 GList* libbalsa_message_header_get_all(LibBalsaMessageHeaders* headers, 312 const gchar *find); 313 const gchar *libbalsa_message_get_user_header(LibBalsaMessage * message, 314 const gchar * name); 315 void libbalsa_message_set_user_header(LibBalsaMessage * message, 316 const gchar * name, 317 const gchar * value); 318 319 LibBalsaMessageBody *libbalsa_message_get_part_by_id(LibBalsaMessage * 320 message, 321 const gchar * id); 322 323 void libbalsa_message_set_dispnotify(LibBalsaMessage *message, 324 InternetAddress *ia); 325 326 void libbalsa_message_set_subject(LibBalsaMessage * message, 327 const gchar * subject); 328 void libbalsa_message_set_subject_from_header(LibBalsaMessage * message, 329 const gchar * header); 330 /* use LIBBALSA_MESSAGE_GET_SUBJECT() macro, we may optimize this 331 function out if we find a way. 332 */ 333 #ifndef MESSAGE_COPY_CONTENT 334 const gchar* libbalsa_message_get_subject(LibBalsaMessage* message); 335 guint libbalsa_message_get_lines(LibBalsaMessage* msg); 336 glong libbalsa_message_get_length(LibBalsaMessage* msg); 337 #endif 338 glong libbalsa_message_get_no(LibBalsaMessage* msg); 339 LibBalsaMessageAttach libbalsa_message_get_attach_icon(LibBalsaMessage * 340 message); 341 #define libbalsa_message_date_to_utf8(m, f) libbalsa_date_to_utf8(&(m)->headers->date, (f)) 342 #define libbalsa_message_headers_date_to_utf8(h, f) libbalsa_date_to_utf8(&(h)->date, (f)) 343 344 GList *libbalsa_message_refs_for_threading(LibBalsaMessage* msg); 345 346 void libbalsa_message_load_envelope_from_stream(LibBalsaMessage * message, 347 GMimeStream * stream); 348 void libbalsa_message_load_envelope(LibBalsaMessage *message); 349 gboolean libbalsa_message_set_headers_from_string(LibBalsaMessage *message, 350 const gchar *str); 351 void libbalsa_message_set_references_from_string(LibBalsaMessage * message, 352 const gchar *str); 353 void libbalsa_message_set_in_reply_to_from_string(LibBalsaMessage * message, 354 const gchar *str); 355 GMimeStream *libbalsa_message_stream(LibBalsaMessage * message); 356 gboolean libbalsa_message_copy(LibBalsaMessage * message, 357 LibBalsaMailbox * dest, GError ** err); 358 void libbalsa_message_change_flags(LibBalsaMessage * message, 359 LibBalsaMessageFlag set, 360 LibBalsaMessageFlag clear); 361 362 const gchar *libbalsa_message_get_tempdir(LibBalsaMessage * message); 363 #endif /* __LIBBALSA_MESSAGE_H__ */ 364