1 /*
2 * e-mail-formatter-utils.h
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "evolution-config.h"
19
20 #include "e-mail-formatter-utils.h"
21 #include "e-mail-part-headers.h"
22
23 #include <string.h>
24 #include <glib/gi18n.h>
25
26 #include <camel/camel.h>
27 #include <libedataserver/libedataserver.h>
28
29 #include <e-util/e-util.h>
30 #include <libemail-engine/libemail-engine.h>
31
32 static const gchar *addrspec_hdrs[] = {
33 "Sender", "From", "Reply-To", "To", "Cc", "Bcc",
34 "Resent-Sender", "Resent-From", "Resent-Reply-To",
35 "Resent-To", "Resent-Cc", "Resent-Bcc", NULL
36 };
37
38 void
e_mail_formatter_format_text_header(EMailFormatter * formatter,GString * buffer,const gchar * label,const gchar * value,guint32 flags)39 e_mail_formatter_format_text_header (EMailFormatter *formatter,
40 GString *buffer,
41 const gchar *label,
42 const gchar *value,
43 guint32 flags)
44 {
45 GtkTextDirection direction;
46 const gchar *fmt, *html;
47 const gchar *display;
48 gchar *mhtml = NULL, *mfmt = NULL;
49
50 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
51 g_return_if_fail (buffer != NULL);
52 g_return_if_fail (label != NULL);
53
54 if (value == NULL)
55 return;
56
57 while (*value == ' ')
58 value++;
59
60 if (!(flags & E_MAIL_FORMATTER_HEADER_FLAG_HTML)) {
61 CamelMimeFilterToHTMLFlags text_format_flags;
62
63 text_format_flags =
64 e_mail_formatter_get_text_format_flags (formatter);
65 html = mhtml = camel_text_to_html (
66 value, text_format_flags, 0);
67 } else {
68 html = value;
69 }
70
71 direction = gtk_widget_get_default_direction ();
72
73 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOCOLUMNS) {
74 if ((flags & E_MAIL_FORMATTER_HEADER_FLAG_BOLD) &&
75 !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NO_FORMATTING)) {
76 fmt = "<tr style=\"display: %s\">"
77 "<td><b>%s:</b> %s</td></tr>";
78 } else {
79 fmt = "<tr style=\"display: %s\">"
80 "<td>%s: %s</td></tr>";
81 }
82 } else {
83 const gchar *decstr;
84 const gchar *dirstr;
85 const gchar *extra_style;
86
87 if ((flags & E_MAIL_FORMATTER_HEADER_FLAG_NODEC) != 0)
88 decstr = "";
89 else
90 decstr = ":";
91
92 if ((flags & E_MAIL_FORMATTER_HEADER_FLAG_NO_FORMATTING) != 0)
93 extra_style = " style=\"font-weight: normal;\"";
94 else
95 extra_style = "";
96
97 if (direction == GTK_TEXT_DIR_RTL)
98 dirstr = "rtl";
99 else
100 dirstr = "ltr";
101
102 mfmt = g_strdup_printf (
103 "<tr class=\"header\" style=\"display: %%s;\">"
104 "<th class=\"header %s\"%s>%%s%s</th>"
105 "<td class=\"header %s\">%%s</td>"
106 "</tr>",
107 dirstr, extra_style, decstr, dirstr);
108 fmt = mfmt;
109 }
110
111 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN)
112 display = "none";
113 else
114 display = "table-row";
115
116 g_string_append_printf (buffer, fmt, display, label, html);
117
118 g_free (mhtml);
119 g_free (mfmt);
120 }
121
122 gchar *
e_mail_formatter_format_address(EMailFormatter * formatter,GString * out,struct _camel_header_address * a,const gchar * field,gboolean no_links,gboolean elipsize)123 e_mail_formatter_format_address (EMailFormatter *formatter,
124 GString *out,
125 struct _camel_header_address *a,
126 const gchar *field,
127 gboolean no_links,
128 gboolean elipsize)
129 {
130 CamelMimeFilterToHTMLFlags flags;
131 gchar *name, *mailto, *addr, *sanitized_addr;
132 gint i = 0;
133 gchar *str = NULL;
134 gint limit = mail_config_get_address_count ();
135 gboolean show_mails = mail_config_get_show_mails_in_preview ();
136
137 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
138 g_return_val_if_fail (out != NULL, NULL);
139 g_return_val_if_fail (field != NULL, NULL);
140
141 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
142
143 while (a != NULL) {
144 if (a->name)
145 name = camel_text_to_html (a->name, flags, 0);
146 else
147 name = NULL;
148
149 switch (a->type) {
150 case CAMEL_HEADER_ADDRESS_NAME:
151 sanitized_addr = camel_utils_sanitize_ascii_domain_in_address (a->v.addr, TRUE);
152 if (name != NULL && *name != '\0') {
153 gchar *real, *mailaddr;
154
155 if (show_mails || no_links) {
156 if (strchr (a->name, ',') || strchr (a->name, ';') || strchr (a->name, '\"') || strchr (a->name, '<') || strchr (a->name, '>'))
157 g_string_append_printf (out, ""%s"", name);
158 else
159 g_string_append (out, name);
160
161 g_string_append (out, " <");
162 }
163
164 /* rfc2368 for mailto syntax and url encoding extras */
165 if ((real = camel_header_encode_phrase ((guchar *) a->name))) {
166 mailaddr = g_strdup_printf ("%s <%s>", real, sanitized_addr ? sanitized_addr : a->v.addr);
167 g_free (real);
168 mailto = camel_url_encode (mailaddr, "?=&()");
169 g_free (mailaddr);
170 } else {
171 mailto = camel_url_encode (sanitized_addr ? sanitized_addr : a->v.addr, "?=&()");
172 }
173 } else {
174 mailto = camel_url_encode (sanitized_addr ? sanitized_addr : a->v.addr, "?=&()");
175 }
176 addr = camel_text_to_html (sanitized_addr ? sanitized_addr : a->v.addr, flags, 0);
177 if (no_links)
178 g_string_append_printf (out, "%s", addr);
179 else if (!show_mails && name && *name)
180 g_string_append_printf (out, "<a href=\"mailto:%s\">%s</a>", mailto, name);
181 else
182 g_string_append_printf (out, "<a href=\"mailto:%s\">%s</a>", mailto, addr);
183 g_free (sanitized_addr);
184 g_free (mailto);
185 g_free (addr);
186
187 if (name != NULL && *name != '\0' && (show_mails || no_links))
188 g_string_append (out, ">");
189 break;
190 case CAMEL_HEADER_ADDRESS_GROUP:
191 g_string_append_printf (out, "%s: ", name);
192 e_mail_formatter_format_address (
193 formatter, out, a->v.members, field,
194 no_links, elipsize);
195 g_string_append_printf (out, ";");
196 break;
197 default:
198 g_warning ("Invalid address type");
199 break;
200 }
201
202 g_free (name);
203
204 i++;
205 a = a->next;
206 if (a != NULL)
207 g_string_append (out, ", ");
208
209 if (!elipsize)
210 continue;
211
212 /* Let us add a '...' if we have more addresses */
213 if (limit > 0 && i == limit && a != NULL) {
214 if (strcmp (field, _("To")) == 0 ||
215 strcmp (field, _("Cc")) == 0 ||
216 strcmp (field, _("Bcc")) == 0) {
217 gint icon_width, icon_height;
218
219 if (!gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height)) {
220 icon_width = 16;
221 icon_height = 16;
222 }
223
224 g_string_append (
225 out,
226 "<span id=\"__evo-moreaddr\" "
227 "style=\"display: none;\">");
228
229 str = g_strdup_printf (
230 "<button type=\"button\" id=\"__evo-moreaddr-button\" class=\"header-collapse\" style=\"display: inline-block;\">"
231 "<img src=\"gtk-stock://pan-end-symbolic?size=%d\" width=\"%dpx\" height=\"%dpx\"/>"
232 "</button>",
233 GTK_ICON_SIZE_BUTTON, icon_width, icon_height);
234 }
235 }
236 }
237
238 if (elipsize && str) {
239 if (strcmp (field, _("To")) == 0 ||
240 strcmp (field, _("Cc")) == 0 ||
241 strcmp (field, _("Bcc")) == 0) {
242
243 g_string_append (
244 out,
245 "</span>"
246 "<span class=\"navigable\" "
247 "id=\"__evo-moreaddr-ellipsis\" "
248 "style=\"display: inline;\">...</span>");
249 }
250 }
251
252 return str;
253 }
254
255 void
e_mail_formatter_canon_header_name(gchar * name)256 e_mail_formatter_canon_header_name (gchar *name)
257 {
258 gchar *inptr = name;
259
260 g_return_if_fail (name != NULL);
261
262 /* canonicalise the header name... first letter is
263 * capitalised and any letter following a '-' also gets
264 * capitalised */
265
266 if (*inptr >= 'a' && *inptr <= 'z')
267 *inptr -= 0x20;
268
269 inptr++;
270
271 while (*inptr) {
272 if (inptr[-1] == '-' && *inptr >= 'a' && *inptr <= 'z')
273 *inptr -= 0x20;
274 else if (inptr[-1] != '-' && *inptr >= 'A' && *inptr <= 'Z')
275 *inptr += 0x20;
276
277 inptr++;
278 }
279 }
280
281 void
e_mail_formatter_format_header(EMailFormatter * formatter,GString * buffer,const gchar * header_name,const gchar * header_value,guint32 flags,const gchar * charset)282 e_mail_formatter_format_header (EMailFormatter *formatter,
283 GString *buffer,
284 const gchar *header_name,
285 const gchar *header_value,
286 guint32 flags,
287 const gchar *charset)
288 {
289 gchar *canon_name, *buf, *value = NULL;
290 const gchar *label, *txt;
291 gboolean addrspec = FALSE;
292 gchar *str_field = NULL;
293 gint i;
294
295 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
296 g_return_if_fail (buffer != NULL);
297 g_return_if_fail (header_name != NULL);
298 g_return_if_fail (header_value != NULL);
299
300 canon_name = g_alloca (strlen (header_name) + 1);
301 strcpy (canon_name, header_name);
302 e_mail_formatter_canon_header_name (canon_name);
303
304 for (i = 0; addrspec_hdrs[i]; i++) {
305 if (g_ascii_strcasecmp (canon_name, addrspec_hdrs[i]) == 0) {
306 addrspec = TRUE;
307 break;
308 }
309 }
310
311 label = _(canon_name);
312
313 if (addrspec) {
314 struct _camel_header_address *addrs;
315 GString *html;
316 gchar *img;
317 gchar *fmt_charset;
318
319 fmt_charset = e_mail_formatter_dup_charset (formatter);
320 if (fmt_charset == NULL)
321 fmt_charset = e_mail_formatter_dup_default_charset (formatter);
322
323 buf = camel_header_unfold (header_value);
324 addrs = camel_header_address_decode (buf, fmt_charset);
325 if (addrs == NULL) {
326 g_free (fmt_charset);
327 g_free (buf);
328 return;
329 }
330
331 g_free (fmt_charset);
332 g_free (buf);
333
334 html = g_string_new ("");
335 img = e_mail_formatter_format_address (
336 formatter, html, addrs, label,
337 (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS),
338 !(flags & E_MAIL_FORMATTER_HEADER_FLAG_NOELIPSIZE));
339
340 if (img != NULL) {
341 str_field = g_strdup_printf ("%s: %s", label, img);
342 label = str_field;
343 flags |= E_MAIL_FORMATTER_HEADER_FLAG_NODEC;
344 g_free (img);
345 }
346
347 camel_header_address_list_clear (&addrs);
348 txt = value = g_string_free (html, FALSE);
349
350 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML;
351 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
352
353 } else if (g_str_equal (canon_name, "Subject")) {
354 buf = camel_header_unfold (header_value);
355 txt = value = camel_header_decode_string (buf, charset);
356 g_free (buf);
357
358 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
359
360 } else if (g_str_equal (canon_name, "X-Evolution-Mailer")) {
361 /* pseudo-header */
362 label = _("Mailer");
363 buf = camel_header_unfold (header_value);
364 txt = value = camel_header_format_ctext (buf, charset);
365 g_free (buf);
366 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
367
368 } else if (g_str_equal (canon_name, "Date") ||
369 g_str_equal (canon_name, "Resent-Date")) {
370 CamelMimeFilterToHTMLFlags text_format_flags;
371 gint msg_offset, local_tz;
372 time_t msg_date;
373 struct tm local;
374 gchar *html;
375 gboolean hide_real_date;
376
377 hide_real_date = !e_mail_formatter_get_show_real_date (formatter);
378
379 txt = header_value;
380 while (*txt == ' ' || *txt == '\t')
381 txt++;
382
383 text_format_flags =
384 e_mail_formatter_get_text_format_flags (formatter);
385
386 html = camel_text_to_html (txt, text_format_flags, 0);
387
388 msg_date = camel_header_decode_date (txt, &msg_offset);
389 e_localtime_with_offset (msg_date, &local, &local_tz);
390
391 /* Convert message offset to minutes (e.g. -0400 --> -240) */
392 msg_offset = ((msg_offset / 100) * 60) + (msg_offset % 100);
393 /* Turn into offset from localtime, not UTC */
394 msg_offset -= local_tz / 60;
395
396 /* value will be freed at the end */
397 if (!hide_real_date && !msg_offset) {
398 /* No timezone difference; just
399 * show the real Date: header. */
400 txt = value = html;
401 } else {
402 gchar *date_str;
403
404 date_str = e_datetime_format_format (
405 "mail", "header",
406 DTFormatKindDateTime, msg_date);
407
408 if (hide_real_date) {
409 /* Show only the local-formatted date, losing
410 * all timezone information like Outlook does.
411 * Should we attempt to show it somehow? */
412 txt = value = date_str;
413 } else {
414 txt = value = g_strdup_printf (
415 "%s (<I>%s</I>)", html, date_str);
416 g_free (date_str);
417 }
418 g_free (html);
419 }
420
421 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML;
422 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
423
424 } else if (g_str_equal (canon_name, "Newsgroups")) {
425 GSList *ng, *scan;
426 GString *html;
427
428 buf = camel_header_unfold (header_value);
429
430 if (!(ng = camel_header_newsgroups_decode (buf))) {
431 g_free (buf);
432 return;
433 }
434
435 g_free (buf);
436
437 html = g_string_new ("");
438 scan = ng;
439 while (scan) {
440 const gchar *newsgroup = scan->data;
441
442 if (flags & E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS)
443 g_string_append_printf (
444 html, "%s", newsgroup);
445 else
446 g_string_append_printf (
447 html, "<a href=\"news:%s\">%s</a>",
448 newsgroup, newsgroup);
449 scan = g_slist_next (scan);
450 if (scan)
451 g_string_append_printf (html, ", ");
452 }
453
454 g_slist_free_full (ng, g_free);
455
456 txt = value = g_string_free (html, FALSE);
457
458 flags |= E_MAIL_FORMATTER_HEADER_FLAG_HTML;
459 flags |= E_MAIL_FORMATTER_HEADER_FLAG_BOLD;
460
461 } else if (g_str_equal (canon_name, "Received") ||
462 g_str_has_prefix (canon_name, "X-") ||
463 g_str_has_prefix (canon_name, "Dkim-") ||
464 g_str_has_prefix (canon_name, "Arc-")) {
465 /* don't unfold Received nor extension headers */
466 txt = value = camel_header_decode_string (header_value, charset);
467 } else {
468 buf = camel_header_unfold (header_value);
469 txt = value = camel_header_decode_string (buf, charset);
470 g_free (buf);
471 }
472
473 e_mail_formatter_format_text_header (
474 formatter, buffer, label, txt, flags);
475
476 g_free (value);
477 g_free (str_field);
478 }
479
480 GList *
e_mail_formatter_find_rfc822_end_iter(GList * rfc822_start_iter)481 e_mail_formatter_find_rfc822_end_iter (GList *rfc822_start_iter)
482 {
483 GList *link = rfc822_start_iter;
484 EMailPart *part;
485 const gchar *part_id;
486 gchar *end;
487
488 g_return_val_if_fail (rfc822_start_iter != NULL, NULL);
489
490 part = E_MAIL_PART (link->data);
491
492 part_id = e_mail_part_get_id (part);
493 g_return_val_if_fail (part_id != NULL, NULL);
494
495 end = g_strconcat (part_id, ".end", NULL);
496
497 while (link != NULL) {
498 part = E_MAIL_PART (link->data);
499
500 part_id = e_mail_part_get_id (part);
501 g_return_val_if_fail (part_id != NULL, NULL);
502
503 if (g_strcmp0 (part_id, end) == 0)
504 break;
505
506 link = g_list_next (link);
507 }
508
509 g_free (end);
510
511 return link;
512 }
513
514 gchar *
e_mail_formatter_parse_html_mnemonics(const gchar * label,gchar ** out_access_key)515 e_mail_formatter_parse_html_mnemonics (const gchar *label,
516 gchar **out_access_key)
517 {
518 const gchar *pos = NULL;
519 GString *html_label = NULL;
520
521 g_return_val_if_fail (label != NULL, NULL);
522
523 if (out_access_key != NULL)
524 *out_access_key = NULL;
525
526 if (!g_utf8_validate (label, -1, NULL)) {
527 gchar *res = g_strdup (label);
528
529 g_return_val_if_fail (g_utf8_validate (label, -1, NULL), res);
530
531 return res;
532 }
533
534 pos = strstr (label, "_");
535 if (pos != NULL) {
536 gunichar uk;
537
538 html_label = g_string_new ("");
539 g_string_append_len (html_label, label, pos - label);
540
541 pos++;
542 uk = g_utf8_get_char (pos);
543
544 pos = g_utf8_next_char (pos);
545
546 g_string_append (html_label, "<u>");
547 g_string_append_unichar (html_label, uk);
548 g_string_append (html_label, "</u>");
549 g_string_append (html_label, pos);
550
551 if (out_access_key != NULL && uk != 0) {
552 gchar ukstr[10];
553 gint len;
554
555 len = g_unichar_to_utf8 (g_unichar_toupper (uk), ukstr);
556 if (len > 0)
557 *out_access_key = g_strndup (ukstr, len);
558 }
559
560 } else {
561 html_label = g_string_new (label);
562 }
563
564 return g_string_free (html_label, FALSE);
565 }
566
567 void
e_mail_formatter_format_security_header(EMailFormatter * formatter,EMailFormatterContext * context,GString * buffer,EMailPart * part,guint32 flags)568 e_mail_formatter_format_security_header (EMailFormatter *formatter,
569 EMailFormatterContext *context,
570 GString *buffer,
571 EMailPart *part,
572 guint32 flags)
573 {
574 struct _validity_flags {
575 guint32 flags;
576 const gchar *description_complete;
577 const gchar *description_partial;
578 } validity_flags[] = {
579 { E_MAIL_PART_VALIDITY_PGP | E_MAIL_PART_VALIDITY_SIGNED, N_("GPG signed"), N_("partially GPG signed") },
580 { E_MAIL_PART_VALIDITY_PGP | E_MAIL_PART_VALIDITY_ENCRYPTED, N_("GPG encrypted"), N_("partially GPG encrypted") },
581 { E_MAIL_PART_VALIDITY_SMIME | E_MAIL_PART_VALIDITY_SIGNED, N_("S/MIME signed"), N_("partially S/MIME signed") },
582 { E_MAIL_PART_VALIDITY_SMIME | E_MAIL_PART_VALIDITY_ENCRYPTED, N_("S/MIME encrypted"), N_("partially S/MIME encrypted") }
583 };
584 const gchar *part_id;
585 gchar *part_id_prefix;
586 GQueue queue = G_QUEUE_INIT;
587 GList *head, *link;
588 guint32 check_valid_flags = 0;
589 gint part_id_prefix_len;
590 gboolean is_partial = FALSE;
591 guint ii;
592
593 g_return_if_fail (E_IS_MAIL_PART_HEADERS (part));
594
595 /* Get prefix of this PURI */
596 part_id = e_mail_part_get_id (part);
597 part_id_prefix = g_strndup (part_id, g_strrstr (part_id, ".") - part_id);
598 part_id_prefix_len = strlen (part_id_prefix);
599
600 e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
601
602 head = g_queue_peek_head_link (&queue);
603
604 /* Ignore the main message, the headers and the end parts */
605 #define should_skip_part(_id) \
606 (g_strcmp0 (_id, part_id_prefix) == 0 || \
607 (_id && g_str_has_suffix (_id, ".rfc822.end")) || \
608 (_id && strlen (_id) == part_id_prefix_len + 8 /* strlen (".headers") */ && \
609 g_strcmp0 (_id + part_id_prefix_len, ".headers") == 0))
610
611 /* Check parts for this ID. */
612 for (link = head; link != NULL; link = g_list_next (link)) {
613 EMailPart *mail_part = link->data;
614 const gchar *id = e_mail_part_get_id (mail_part);
615
616 if (!e_mail_part_id_has_prefix (mail_part, part_id_prefix))
617 continue;
618
619 if (should_skip_part (id))
620 continue;
621
622 if (!e_mail_part_has_validity (mail_part)) {
623 /* A part without validity, thus it's partially signed/encrypted */
624 is_partial = TRUE;
625 } else {
626 guint32 validies = 0;
627 for (ii = 0; ii < G_N_ELEMENTS (validity_flags); ii++) {
628 if (e_mail_part_get_validity (mail_part, validity_flags[ii].flags))
629 validies |= validity_flags[ii].flags;
630 }
631 check_valid_flags |= validies;
632 }
633
634 /* Do not traverse sub-messages */
635 if (g_str_has_suffix (e_mail_part_get_id (mail_part), ".rfc822") &&
636 !g_str_equal (e_mail_part_get_id (mail_part), part_id_prefix))
637 link = e_mail_formatter_find_rfc822_end_iter (link);
638 }
639
640 if (check_valid_flags) {
641 GString *tmp;
642
643 if (!is_partial) {
644 for (link = head; link != NULL && !is_partial; link = g_list_next (link)) {
645 EMailPart *mail_part = link->data;
646 const gchar *id = e_mail_part_get_id (mail_part);
647
648 if (!e_mail_part_id_has_prefix (mail_part, part_id_prefix))
649 continue;
650
651 if (should_skip_part (id))
652 continue;
653
654 if (!e_mail_part_has_validity (mail_part)) {
655 /* A part without validity, thus it's partially signed/encrypted */
656 is_partial = TRUE;
657 break;
658 }
659
660 is_partial = !e_mail_part_get_validity (mail_part, check_valid_flags);
661
662 /* Do not traverse sub-messages */
663 if (g_str_has_suffix (e_mail_part_get_id (mail_part), ".rfc822") &&
664 !g_str_equal (e_mail_part_get_id (mail_part), part_id_prefix))
665 link = e_mail_formatter_find_rfc822_end_iter (link);
666 }
667 }
668
669 /* Add encryption/signature header */
670 tmp = g_string_new ("");
671
672 for (link = head; link; link = g_list_next (link)) {
673 EMailPart *mail_part = link->data;
674 const gchar *id = e_mail_part_get_id (mail_part);
675
676 if (!e_mail_part_has_validity (mail_part) ||
677 !e_mail_part_id_has_prefix (mail_part, part_id_prefix))
678 continue;
679
680 if (should_skip_part (id))
681 continue;
682
683 for (ii = 0; ii < G_N_ELEMENTS (validity_flags); ii++) {
684 if (e_mail_part_get_validity (mail_part, validity_flags[ii].flags)) {
685 if (tmp->len > 0)
686 g_string_append (tmp, ", ");
687 g_string_append (tmp, is_partial ? _(validity_flags[ii].description_partial) : _(validity_flags[ii].description_complete));
688 }
689 }
690
691 break;
692 }
693
694 if (tmp->len > 0)
695 e_mail_formatter_format_header (formatter, buffer, _("Security"), tmp->str, flags, "UTF-8");
696
697 g_string_free (tmp, TRUE);
698 }
699
700 #undef should_skip_part
701
702 while (!g_queue_is_empty (&queue))
703 g_object_unref (g_queue_pop_head (&queue));
704
705 g_free (part_id_prefix);
706 }
707