2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "claws-features.h"
41 #include "mailimf_write.h"
46 #include "file-utils.h"
48 #define MAX_MAIL_COL 72
58 #define MAX_VALID_IMF_LINE 998
60 static int mailimf_orig_date_write(FILE * f
, int * col
,
61 struct mailimf_orig_date
* date
);
62 static int mailimf_date_time_write(FILE * f
, int * col
,
63 struct mailimf_date_time
* date_time
);
64 static int mailimf_from_write(FILE * f
, int * col
,
65 struct mailimf_from
* from
);
66 static int mailimf_sender_write(FILE * f
, int * col
,
67 struct mailimf_sender
* sender
);
68 static int mailimf_reply_to_write(FILE * f
, int * col
,
69 struct mailimf_reply_to
* reply_to
);
70 static int mailimf_to_write(FILE * f
, int * col
,
71 struct mailimf_to
* to
);
72 static int mailimf_cc_write(FILE * f
, int * col
,
73 struct mailimf_cc
* to
);
74 static int mailimf_bcc_write(FILE * f
, int * col
,
75 struct mailimf_bcc
* to
);
76 static int mailimf_message_id_write(FILE * f
, int * col
,
77 struct mailimf_message_id
* message_id
);
78 static int mailimf_msg_id_list_write(FILE * f
, int * col
,
80 static int mailimf_in_reply_to_write(FILE * f
, int * col
,
81 struct mailimf_in_reply_to
*
83 static int mailimf_references_write(FILE * f
, int * col
,
84 struct mailimf_references
* references
);
85 static int mailimf_subject_write(FILE * f
, int * col
,
86 struct mailimf_subject
* subject
);
88 static int mailimf_address_write(FILE * f
, int * col
,
89 struct mailimf_address
* addr
);
90 static int mailimf_group_write(FILE * f
, int * col
,
91 struct mailimf_group
* group
);
93 static int mailimf_mailbox_write(FILE * f
, int * col
,
94 struct mailimf_mailbox
* mb
);
96 static int mailimf_comments_write(FILE * f
, int * col
,
97 struct mailimf_comments
* comments
);
99 static int mailimf_optional_field_write(FILE * f
, int * col
,
100 struct mailimf_optional_field
* field
);
102 static int mailimf_keywords_write(FILE * f
, int * col
,
103 struct mailimf_keywords
* keywords
);
105 static int mailimf_return_write(FILE * f
, int * col
,
106 struct mailimf_return
* return_path
);
108 static int mailimf_path_write(FILE * f
, int * col
,
109 struct mailimf_path
* path
);
111 static int mailimf_resent_date_write(FILE * f
, int * col
,
112 struct mailimf_orig_date
* date
);
114 static int mailimf_resent_from_write(FILE * f
, int * col
,
115 struct mailimf_from
* from
);
117 static int mailimf_resent_sender_write(FILE * f
, int * col
,
118 struct mailimf_sender
* sender
);
120 static int mailimf_resent_to_write(FILE * f
, int * col
,
121 struct mailimf_to
* to
);
123 static int mailimf_resent_cc_write(FILE * f
, int * col
,
124 struct mailimf_cc
* cc
);
126 static int mailimf_resent_bcc_write(FILE * f
, int * col
,
127 struct mailimf_bcc
* bcc
);
130 mailimf_resent_msg_id_write(FILE * f
, int * col
,
131 struct mailimf_message_id
* message_id
);
135 /* ************************ */
138 #define HEADER_FOLD "\r\n "
140 static inline int flush_buf(FILE * f
, const char * str
, size_t length
)
145 r
= claws_fwrite(str
, 1, length
, f
);
147 return MAILIMF_ERROR_FILE
;
149 return MAILIMF_NO_ERROR
;
152 #define CUT_AT_MAX_VALID_IMF_LINE
154 int mailimf_string_write(FILE * f
, int * col
,
155 const char * str
, size_t length
)
159 const char * block_begin
;
168 #ifdef CUT_AT_MAX_VALID_IMF_LINE
171 cut lines at maximum valid length for internet message
172 format standard (currently RFC 2822)
174 This should not happen.
175 In case there are some lines larger than 998 in body,
176 the encoding must be changed into base64 or quoted-printable
177 so that wrapping to 72 columns is done.
180 r
= flush_buf(f
, block_begin
, count
);
181 if (r
!= MAILIMF_NO_ERROR
)
184 r
= claws_fwrite(CRLF
, 1, sizeof(CRLF
) - 1, f
);
186 return MAILIMF_ERROR_FILE
;
196 r
= flush_buf(f
, block_begin
, count
);
197 if (r
!= MAILIMF_NO_ERROR
)
200 r
= claws_fwrite(CRLF
, 1, sizeof(CRLF
) - 1, f
);
202 return MAILIMF_ERROR_FILE
;
215 if (* (p
+ 1) == '\n') {
216 r
= flush_buf(f
, block_begin
, count
);
217 if (r
!= MAILIMF_NO_ERROR
)
220 r
= claws_fwrite(CRLF
, 1, sizeof(CRLF
) - 1, f
);
222 return MAILIMF_ERROR_FILE
;
235 r
= flush_buf(f
, block_begin
, count
);
236 if (r
!= MAILIMF_NO_ERROR
)
239 r
= claws_fwrite(CRLF
, 1, sizeof(CRLF
) - 1, f
);
241 return MAILIMF_ERROR_FILE
;
260 r
= flush_buf(f
, block_begin
, count
);
261 if (r
!= MAILIMF_NO_ERROR
)
265 return MAILIMF_NO_ERROR
;
269 int mailimf_header_string_write(FILE * f
, int * col
,
270 char * str
, size_t length
)
279 if (* col
+ length
< MAX_MAIL_COL
)
280 return mailimf_string_write(f
, col
, str
, length
);
285 last_cut
= block_begin
;
289 if (current_col
>= MAX_MAIL_COL
) {
290 /* if we reach the maximum recommanded size of line */
291 if (last_cut
== block_begin
) {
292 /* if we could not find any place to cut */
294 /* fold the header */
295 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
296 sizeof(HEADER_FOLD
) - 1);
297 if (r
!= MAILIMF_NO_ERROR
)
299 current_col
= * col
+ p
- block_begin
;
304 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
305 if (r
!= MAILIMF_NO_ERROR
)
307 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
308 sizeof(HEADER_FOLD
) - 1);
309 if (r
!= MAILIMF_NO_ERROR
)
313 last_cut
= block_begin
;
314 current_col
= * col
+ p
- block_begin
;
318 /* if we found a place to cut */
319 r
= mailimf_string_write(f
, col
, block_begin
, last_cut
- block_begin
);
320 if (r
!= MAILIMF_NO_ERROR
)
322 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
323 sizeof(HEADER_FOLD
) - 1);
324 if (r
!= MAILIMF_NO_ERROR
)
327 block_begin
= last_cut
;
328 last_cut
= block_begin
;
329 current_col
= * col
+ p
- block_begin
;
359 return mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
372 int mailimf_header_string_write(FILE * f
, int * col
,
373 const char * str
, size_t length
)
377 const char * block_begin
;
382 if (* col
< MAX_MAIL_COL
)
383 state
= STATE_LOWER_72_CUT
;
384 else if (* col
== MAX_MAIL_COL
)
385 state
= STATE_EQUAL_72
;
386 else if (* col
< MAX_VALID_IMF_LINE
)
387 state
= STATE_LOWER_998
;
389 state
= STATE_EQUAL_998
;
413 state
= STATE_LOWER_72_CUT
;
417 if (size
< MAX_MAIL_COL
- 1) {
423 state
= STATE_EQUAL_72
;
430 break; /* end of STATE_LOWER_72 */
432 case STATE_LOWER_72_CUT
:
439 state
= STATE_LOWER_72
;
451 if (size
< MAX_MAIL_COL
) {
457 r
= mailimf_string_write(f
, col
, block_begin
, cut
- block_begin
);
458 if (r
!= MAILIMF_NO_ERROR
)
460 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
461 sizeof(HEADER_FOLD
) - 1);
462 if (r
!= MAILIMF_NO_ERROR
)
467 if ((* block_begin
== ' ') || (* block_begin
== '\t'))
469 size
= p
- block_begin
+ * col
;
470 state
= STATE_LOWER_72
;
474 break; /* end of STATE_LOWER_72_CUT */
483 state
= STATE_LOWER_72
;
488 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
489 if (r
!= MAILIMF_NO_ERROR
)
491 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
492 sizeof(HEADER_FOLD
) - 1);
493 if (r
!= MAILIMF_NO_ERROR
)
498 size
= p
- block_begin
+ * col
;
499 state
= STATE_LOWER_72
;
506 state
= STATE_LOWER_998
;
509 break; /* end of STATE_EQUAL_72 */
511 case STATE_LOWER_998
:
518 state
= STATE_LOWER_72
;
523 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
524 if (r
!= MAILIMF_NO_ERROR
)
526 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
527 sizeof(HEADER_FOLD
) - 1);
528 if (r
!= MAILIMF_NO_ERROR
)
533 size
= p
- block_begin
+ * col
;
534 state
= STATE_LOWER_72
;
538 if (size
< MAX_VALID_IMF_LINE
- 1) {
547 state
= STATE_EQUAL_998
;
551 break; /* end of STATE_LOWER_998 */
553 case STATE_EQUAL_998
:
560 state
= STATE_LOWER_72
;
565 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
566 if (r
!= MAILIMF_NO_ERROR
)
568 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
569 sizeof(HEADER_FOLD
) - 1);
570 if (r
!= MAILIMF_NO_ERROR
)
575 size
= p
- block_begin
+ * col
;
576 state
= STATE_LOWER_72
;
580 #ifdef CUT_AT_MAX_VALID_IMF_LINE
581 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
582 if (r
!= MAILIMF_NO_ERROR
)
584 r
= mailimf_string_write(f
, col
, HEADER_FOLD
,
585 sizeof(HEADER_FOLD
) - 1);
586 if (r
!= MAILIMF_NO_ERROR
)
591 size
= p
- block_begin
+ * col
;
592 state
= STATE_LOWER_72
;
600 break; /* end of STATE_EQUAL_998 */
604 r
= mailimf_string_write(f
, col
, block_begin
, p
- block_begin
);
605 if (r
!= MAILIMF_NO_ERROR
)
608 return MAILIMF_NO_ERROR
;
618 int mailimf_header_string_write(FILE * f
, int * col
,
619 const char * str
, size_t length
)
623 const char * word_begin
;
674 if (p
- word_begin
+ (* col
) + 1 > MAX_MAIL_COL
)
675 mailimf_string_write(f
, col
, HEADER_FOLD
,
676 sizeof(HEADER_FOLD
) - 1);
679 mailimf_string_write(f
, col
, " ", 1);
682 mailimf_string_write(f
, col
, word_begin
, p
- word_begin
);
687 if (p
- word_begin
+ (* col
) >= MAX_VALID_IMF_LINE
) {
688 mailimf_string_write(f
, col
, word_begin
, p
- word_begin
);
689 mailimf_string_write(f
, col
, HEADER_FOLD
,
690 sizeof(HEADER_FOLD
) - 1);
701 if (state
== STATE_WORD
) {
702 if (p
- word_begin
+ (* col
) >= MAX_MAIL_COL
)
703 mailimf_string_write(f
, col
, HEADER_FOLD
,
704 sizeof(HEADER_FOLD
) - 1);
707 mailimf_string_write(f
, col
, " ", 1);
710 mailimf_string_write(f
, col
, word_begin
, p
- word_begin
);
713 return MAILIMF_NO_ERROR
;
716 int mailimf_envelope_fields_write(FILE * f
, int * col
,
717 struct mailimf_fields
* fields
)
721 for(cur
= clist_begin(fields
->fld_list
) ; cur
!= NULL
;
722 cur
= clist_next(cur
)) {
724 struct mailimf_field
* field
;
726 field
= clist_content(cur
);
727 if (field
->fld_type
!= MAILIMF_FIELD_OPTIONAL_FIELD
) {
728 r
= mailimf_field_write(f
, col
, field
);
729 if (r
!= MAILIMF_NO_ERROR
)
734 return MAILIMF_NO_ERROR
;
737 int mailimf_fields_write(FILE * f
, int * col
,
738 struct mailimf_fields
* fields
)
742 for(cur
= clist_begin(fields
->fld_list
) ; cur
!= NULL
;
743 cur
= clist_next(cur
)) {
746 r
= mailimf_field_write(f
, col
, clist_content(cur
));
747 if (r
!= MAILIMF_NO_ERROR
)
751 return MAILIMF_NO_ERROR
;
755 int mailimf_unparsed_fields_write(FILE * f
, int * col
,
756 struct mailimf_unparsed_fields
* fields
)
760 for(cur
= clist_begin(fields
->list
) ; cur
!= NULL
; cur
= cur
->next
) {
763 r
= mailimf_optional_field_write(f
, col
, cur
->data
);
764 if (r
!= MAILIMF_NO_ERROR
)
768 return MAILIMF_NO_ERROR
;
772 int mailimf_field_write(FILE * f
, int * col
,
773 struct mailimf_field
* field
)
777 switch (field
->fld_type
) {
778 case MAILIMF_FIELD_RETURN_PATH
:
779 r
= mailimf_return_write(f
, col
, field
->fld_data
.fld_return_path
);
781 case MAILIMF_FIELD_RESENT_DATE
:
782 r
= mailimf_resent_date_write(f
, col
, field
->fld_data
.fld_resent_date
);
784 case MAILIMF_FIELD_RESENT_FROM
:
785 r
= mailimf_resent_from_write(f
, col
, field
->fld_data
.fld_resent_from
);
787 case MAILIMF_FIELD_RESENT_SENDER
:
788 r
= mailimf_resent_sender_write(f
, col
, field
->fld_data
.fld_resent_sender
);
790 case MAILIMF_FIELD_RESENT_TO
:
791 r
= mailimf_resent_to_write(f
, col
, field
->fld_data
.fld_resent_to
);
793 case MAILIMF_FIELD_RESENT_CC
:
794 r
= mailimf_resent_cc_write(f
, col
, field
->fld_data
.fld_resent_cc
);
796 case MAILIMF_FIELD_RESENT_BCC
:
797 r
= mailimf_resent_bcc_write(f
, col
, field
->fld_data
.fld_resent_bcc
);
799 case MAILIMF_FIELD_RESENT_MSG_ID
:
800 r
= mailimf_resent_msg_id_write(f
, col
, field
->fld_data
.fld_resent_msg_id
);
802 case MAILIMF_FIELD_ORIG_DATE
:
803 r
= mailimf_orig_date_write(f
, col
, field
->fld_data
.fld_orig_date
);
805 case MAILIMF_FIELD_FROM
:
806 r
= mailimf_from_write(f
, col
, field
->fld_data
.fld_from
);
808 case MAILIMF_FIELD_SENDER
:
809 r
= mailimf_sender_write(f
, col
, field
->fld_data
.fld_sender
);
811 case MAILIMF_FIELD_REPLY_TO
:
812 r
= mailimf_reply_to_write(f
, col
, field
->fld_data
.fld_reply_to
);
814 case MAILIMF_FIELD_TO
:
815 r
= mailimf_to_write(f
, col
, field
->fld_data
.fld_to
);
817 case MAILIMF_FIELD_CC
:
818 r
= mailimf_cc_write(f
, col
, field
->fld_data
.fld_cc
);
820 case MAILIMF_FIELD_BCC
:
821 r
= mailimf_bcc_write(f
, col
, field
->fld_data
.fld_bcc
);
823 case MAILIMF_FIELD_MESSAGE_ID
:
824 r
= mailimf_message_id_write(f
, col
, field
->fld_data
.fld_message_id
);
826 case MAILIMF_FIELD_IN_REPLY_TO
:
827 r
= mailimf_in_reply_to_write(f
, col
, field
->fld_data
.fld_in_reply_to
);
829 case MAILIMF_FIELD_REFERENCES
:
830 r
= mailimf_references_write(f
, col
, field
->fld_data
.fld_references
);
832 case MAILIMF_FIELD_SUBJECT
:
833 r
= mailimf_subject_write(f
, col
, field
->fld_data
.fld_subject
);
835 case MAILIMF_FIELD_COMMENTS
:
836 r
= mailimf_comments_write(f
, col
, field
->fld_data
.fld_comments
);
838 case MAILIMF_FIELD_KEYWORDS
:
839 r
= mailimf_keywords_write(f
, col
, field
->fld_data
.fld_keywords
);
841 case MAILIMF_FIELD_OPTIONAL_FIELD
:
842 r
= mailimf_optional_field_write(f
, col
, field
->fld_data
.fld_optional_field
);
845 r
= MAILIMF_ERROR_INVAL
;
849 if (r
!= MAILIMF_NO_ERROR
)
852 return MAILIMF_NO_ERROR
;
856 static int mailimf_orig_date_write(FILE * f
, int * col
,
857 struct mailimf_orig_date
* date
)
861 r
= mailimf_string_write(f
, col
, "Date: ", 6);
862 if (r
!= MAILIMF_NO_ERROR
)
865 r
= mailimf_date_time_write(f
, col
, date
->dt_date_time
);
866 if (r
!= MAILIMF_NO_ERROR
)
869 r
= mailimf_string_write(f
, col
, "\r\n", 2);
870 if (r
!= MAILIMF_NO_ERROR
)
876 return MAILIMF_NO_ERROR
;
879 #define MAX_DATE_STR 256
884 static int dayofweek(int year
, int month
, int day
)
886 static int offset
[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
890 return (year
+ year
/4 - year
/100 + year
/400 + offset
[month
-1] + day
) % 7;
893 static const char * week_of_day_str
[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
895 static const char * month_str
[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
896 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
898 static int mailimf_date_time_write(FILE * f
, int * col
,
899 struct mailimf_date_time
* date_time
)
902 char date_str
[MAX_DATE_STR
];
910 tmval
.tm_sec
= date_time
->sec
;
911 tmval
.tm_min
= date_time
->min
;
912 tmval
.tm_hour
= date_time
->hour
;
913 tmval
.tm_sec
= date_time
->sec
;
914 tmval
.tm_mday
= date_time
->day
;
915 tmval
.tm_mon
= date_time
->month
- 1;
916 tmval
.tm_year
= date_time
->year
- 1900;
919 timeval
= mktime(&tmval
);
921 localtime_r(&timeval
, &tmval
);
924 wday
= dayofweek(date_time
->dt_year
, date_time
->dt_month
, date_time
->dt_day
);
926 snprintf(date_str
, MAX_DATE_STR
, "%s, %i %s %i %02i:%02i:%02i %+05i",
927 week_of_day_str
[wday
], date_time
->dt_day
,
928 month_str
[date_time
->dt_month
- 1],
929 date_time
->dt_year
, date_time
->dt_hour
,
930 date_time
->dt_min
, date_time
->dt_sec
,
933 r
= mailimf_string_write(f
, col
, date_str
, strlen(date_str
));
935 if (r
!= MAILIMF_NO_ERROR
)
938 return MAILIMF_NO_ERROR
;
941 static int mailimf_from_write(FILE * f
, int * col
,
942 struct mailimf_from
* from
)
946 r
= mailimf_string_write(f
, col
, "From: ", 6);
947 if (r
!= MAILIMF_NO_ERROR
)
950 r
= mailimf_mailbox_list_write(f
, col
, from
->frm_mb_list
);
951 if (r
!= MAILIMF_NO_ERROR
)
954 r
= mailimf_string_write(f
, col
, "\r\n", 2);
955 if (r
!= MAILIMF_NO_ERROR
)
961 return MAILIMF_NO_ERROR
;
964 static int mailimf_sender_write(FILE * f
, int * col
,
965 struct mailimf_sender
* sender
)
969 r
= mailimf_string_write(f
, col
, "Sender: ", 8);
970 if (r
!= MAILIMF_NO_ERROR
)
973 r
= mailimf_mailbox_write(f
, col
, sender
->snd_mb
);
974 if (r
!= MAILIMF_NO_ERROR
)
977 r
= mailimf_string_write(f
, col
, "\r\n", 2);
978 if (r
!= MAILIMF_NO_ERROR
)
984 return MAILIMF_NO_ERROR
;
987 static int mailimf_reply_to_write(FILE * f
, int * col
,
988 struct mailimf_reply_to
* reply_to
)
992 r
= mailimf_string_write(f
, col
, "Reply-To: ", 10);
993 if (r
!= MAILIMF_NO_ERROR
)
996 r
= mailimf_address_list_write(f
, col
, reply_to
->rt_addr_list
);
997 if (r
!= MAILIMF_NO_ERROR
)
1000 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1001 if (r
!= MAILIMF_NO_ERROR
)
1007 return MAILIMF_NO_ERROR
;
1011 static int mailimf_to_write(FILE * f
, int * col
,
1012 struct mailimf_to
* to
)
1016 r
= mailimf_string_write(f
, col
, "To: ", 4);
1017 if (r
!= MAILIMF_NO_ERROR
)
1020 r
= mailimf_address_list_write(f
, col
, to
->to_addr_list
);
1021 if (r
!= MAILIMF_NO_ERROR
)
1024 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1025 if (r
!= MAILIMF_NO_ERROR
)
1031 return MAILIMF_NO_ERROR
;
1035 static int mailimf_cc_write(FILE * f
, int * col
,
1036 struct mailimf_cc
* cc
)
1040 r
= mailimf_string_write(f
, col
, "Cc: ", 4);
1041 if (r
!= MAILIMF_NO_ERROR
)
1044 r
= mailimf_address_list_write(f
, col
, cc
->cc_addr_list
);
1045 if (r
!= MAILIMF_NO_ERROR
)
1048 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1049 if (r
!= MAILIMF_NO_ERROR
)
1055 return MAILIMF_NO_ERROR
;
1059 static int mailimf_bcc_write(FILE * f
, int * col
,
1060 struct mailimf_bcc
* bcc
)
1064 r
= mailimf_string_write(f
, col
, "Bcc: ", 5);
1065 if (r
!= MAILIMF_NO_ERROR
)
1068 if (bcc
->bcc_addr_list
!= NULL
) {
1069 r
= mailimf_address_list_write(f
, col
, bcc
->bcc_addr_list
);
1070 if (r
!= MAILIMF_NO_ERROR
)
1074 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1075 if (r
!= MAILIMF_NO_ERROR
)
1081 return MAILIMF_NO_ERROR
;
1085 static int mailimf_message_id_write(FILE * f
, int * col
,
1086 struct mailimf_message_id
* message_id
)
1090 r
= mailimf_string_write(f
, col
, "Message-ID: ", 12);
1091 if (r
!= MAILIMF_NO_ERROR
)
1094 r
= mailimf_string_write(f
, col
, "<", 1);
1095 if (r
!= MAILIMF_NO_ERROR
)
1098 r
= mailimf_string_write(f
, col
,
1099 message_id
->mid_value
,
1100 strlen(message_id
->mid_value
));
1101 if (r
!= MAILIMF_NO_ERROR
)
1104 r
= mailimf_string_write(f
, col
, ">", 1);
1105 if (r
!= MAILIMF_NO_ERROR
)
1108 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1109 if (r
!= MAILIMF_NO_ERROR
)
1115 return MAILIMF_NO_ERROR
;
1119 static int mailimf_msg_id_list_write(FILE * f
, int * col
, clist
* mid_list
)
1127 for(cur
= clist_begin(mid_list
) ; cur
!= NULL
; cur
= clist_next(cur
)) {
1131 msgid
= clist_content(cur
);
1132 len
= strlen(msgid
);
1135 XXX - if this is the first message ID, don't fold.
1136 This is a workaround for a bug of old versions of INN.
1141 if (* col
+ len
>= MAX_MAIL_COL
) {
1142 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1143 if (r
!= MAILIMF_NO_ERROR
)
1154 r
= mailimf_string_write(f
, col
, " ", 1);
1155 if (r
!= MAILIMF_NO_ERROR
)
1162 r
= mailimf_string_write(f
, col
, "<", 1);
1163 if (r
!= MAILIMF_NO_ERROR
)
1166 r
= mailimf_string_write(f
, col
, msgid
, len
);
1167 if (r
!= MAILIMF_NO_ERROR
)
1170 r
= mailimf_string_write(f
, col
, ">", 1);
1171 if (r
!= MAILIMF_NO_ERROR
)
1175 return MAILIMF_NO_ERROR
;
1179 static int mailimf_in_reply_to_write(FILE * f
, int * col
,
1180 struct mailimf_in_reply_to
* in_reply_to
)
1184 r
= mailimf_string_write(f
, col
, "In-Reply-To: ", 13);
1185 if (r
!= MAILIMF_NO_ERROR
)
1188 r
= mailimf_msg_id_list_write(f
, col
, in_reply_to
->mid_list
);
1189 if (r
!= MAILIMF_NO_ERROR
)
1192 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1193 if (r
!= MAILIMF_NO_ERROR
)
1199 return MAILIMF_NO_ERROR
;
1203 static int mailimf_references_write(FILE * f
, int * col
,
1204 struct mailimf_references
* references
)
1208 r
= mailimf_string_write(f
, col
, "References: ", 12);
1209 if (r
!= MAILIMF_NO_ERROR
)
1212 r
= mailimf_msg_id_list_write(f
, col
, references
->mid_list
);
1213 if (r
!= MAILIMF_NO_ERROR
)
1216 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1217 if (r
!= MAILIMF_NO_ERROR
)
1223 return MAILIMF_NO_ERROR
;
1228 static int mailimf_subject_write(FILE * f
, int * col
,
1229 struct mailimf_subject
* subject
)
1233 r
= mailimf_string_write(f
, col
, "Subject: ", 9);
1234 if (r
!= MAILIMF_NO_ERROR
)
1237 r
= mailimf_header_string_write(f
, col
,
1238 subject
->sbj_value
, strlen(subject
->sbj_value
));
1239 if (r
!= MAILIMF_NO_ERROR
)
1242 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1243 if (r
!= MAILIMF_NO_ERROR
)
1249 return MAILIMF_NO_ERROR
;
1252 int mailimf_address_list_write(FILE * f
, int * col
,
1253 struct mailimf_address_list
* addr_list
)
1261 for(cur
= clist_begin(addr_list
->ad_list
) ; cur
!= NULL
;
1262 cur
= clist_next(cur
)) {
1263 struct mailimf_address
* addr
;
1265 addr
= clist_content(cur
);
1268 r
= mailimf_string_write(f
, col
, ", ", 2);
1269 if (r
!= MAILIMF_NO_ERROR
)
1276 r
= mailimf_address_write(f
, col
, addr
);
1277 if (r
!= MAILIMF_NO_ERROR
)
1281 return MAILIMF_NO_ERROR
;
1285 static int mailimf_address_write(FILE * f
, int * col
,
1286 struct mailimf_address
* addr
)
1290 switch(addr
->ad_type
) {
1291 case MAILIMF_ADDRESS_MAILBOX
:
1292 r
= mailimf_mailbox_write(f
, col
, addr
->ad_data
.ad_mailbox
);
1293 if (r
!= MAILIMF_NO_ERROR
)
1298 case MAILIMF_ADDRESS_GROUP
:
1299 r
= mailimf_group_write(f
, col
, addr
->ad_data
.ad_group
);
1300 if (r
!= MAILIMF_NO_ERROR
)
1306 return MAILIMF_NO_ERROR
;
1310 static int mailimf_group_write(FILE * f
, int * col
,
1311 struct mailimf_group
* group
)
1315 r
= mailimf_header_string_write(f
, col
, group
->grp_display_name
,
1316 strlen(group
->grp_display_name
));
1317 if (r
!= MAILIMF_NO_ERROR
)
1320 r
= mailimf_string_write(f
, col
, ": ", 2);
1321 if (r
!= MAILIMF_NO_ERROR
)
1324 if (group
->grp_mb_list
!= NULL
) {
1325 r
= mailimf_mailbox_list_write(f
, col
, group
->grp_mb_list
);
1326 if (r
!= MAILIMF_NO_ERROR
)
1330 r
= mailimf_string_write(f
, col
, ";", 1);
1331 if (r
!= MAILIMF_NO_ERROR
)
1334 return MAILIMF_NO_ERROR
;
1338 int mailimf_mailbox_list_write(FILE * f
, int * col
,
1339 struct mailimf_mailbox_list
* mb_list
)
1347 for(cur
= clist_begin(mb_list
->mb_list
) ; cur
!= NULL
;
1348 cur
= clist_next(cur
)) {
1349 struct mailimf_mailbox
* mb
;
1351 mb
= clist_content(cur
);
1354 r
= mailimf_string_write(f
, col
, ", ", 2);
1355 if (r
!= MAILIMF_NO_ERROR
)
1362 r
= mailimf_mailbox_write(f
, col
, mb
);
1363 if (r
!= MAILIMF_NO_ERROR
)
1367 return MAILIMF_NO_ERROR
;
1371 int mailimf_quoted_string_write(FILE * f
, int * col
,
1372 const char * string
, size_t len
)
1377 if (claws_fputc('\"', f
) < 0)
1378 return MAILIMF_ERROR_FILE
;
1379 for(i
= 0 ; i
< len
; i
++) {
1380 switch (string
[i
]) {
1383 r
= claws_fputc('\\', f
);
1385 return MAILIMF_ERROR_FILE
;
1386 r
= claws_fputc(string
[i
], f
);
1388 return MAILIMF_ERROR_FILE
;
1393 r
= claws_fputc(string
[i
], f
);
1395 return MAILIMF_ERROR_FILE
;
1400 if (claws_fputc('\"', f
) < 0)
1401 return MAILIMF_ERROR_FILE
;
1403 return MAILIMF_NO_ERROR
;
1409 atext = ALPHA / DIGIT / ; Any character except controls,
1410 "!" / "#" / ; SP, and specials.
1411 "$" / "%" / ; Used for atoms
1422 static int is_atext(const char * s
)
1426 for(p
= s
; * p
!= 0 ; p
++) {
1427 if (isalpha((unsigned char) * p
))
1429 if (isdigit((unsigned char) * p
))
1462 static int mailimf_mailbox_write(FILE * f
, int * col
,
1463 struct mailimf_mailbox
* mb
)
1471 if (mb
->mb_display_name
!= NULL
) {
1472 if (* col
+ strlen(mb
->mb_display_name
) >= MAX_MAIL_COL
) {
1473 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1474 if (r
!= MAILIMF_NO_ERROR
)
1484 if (mb
->mb_display_name
) {
1486 if (is_atext(mb
->mb_display_name
)) {
1487 r
= mailimf_header_string_write(f
, col
, mb
->mb_display_name
,
1488 strlen(mb
->mb_display_name
));
1489 if (r
!= MAILIMF_NO_ERROR
)
1493 if (mb
->mb_display_name
!= NULL
) {
1494 if (* col
+ strlen(mb
->mb_display_name
) >= MAX_MAIL_COL
) {
1495 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1496 if (r
!= MAILIMF_NO_ERROR
)
1501 if (strlen(mb
->mb_display_name
) > MAX_VALID_IMF_LINE
/ 2)
1502 return MAILIMF_ERROR_INVAL
;
1504 r
= mailimf_quoted_string_write(f
, col
, mb
->mb_display_name
,
1505 strlen(mb
->mb_display_name
));
1506 if (r
!= MAILIMF_NO_ERROR
)
1513 if (* col
+ strlen(mb
->mb_addr_spec
) + 3 >= MAX_MAIL_COL
) {
1514 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1515 if (r
!= MAILIMF_NO_ERROR
)
1525 r
= mailimf_string_write(f
, col
, "<", 1);
1527 r
= mailimf_string_write(f
, col
, " <", 2);
1528 if (r
!= MAILIMF_NO_ERROR
)
1531 r
= mailimf_string_write(f
, col
, mb
->mb_addr_spec
,
1532 strlen(mb
->mb_addr_spec
));
1533 if (r
!= MAILIMF_NO_ERROR
)
1536 r
= mailimf_string_write(f
, col
, ">", 1);
1537 if (r
!= MAILIMF_NO_ERROR
)
1541 if (* col
+ strlen(mb
->mb_addr_spec
) >= MAX_MAIL_COL
) {
1542 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1543 if (r
!= MAILIMF_NO_ERROR
)
1547 r
= mailimf_string_write(f
, col
,
1548 mb
->mb_addr_spec
, strlen(mb
->mb_addr_spec
));
1549 if (r
!= MAILIMF_NO_ERROR
)
1554 return MAILIMF_NO_ERROR
;
1557 static int mailimf_comments_write(FILE * f
, int * col
,
1558 struct mailimf_comments
* comments
)
1562 r
= mailimf_string_write(f
, col
, "Comments: ", 10);
1563 if (r
!= MAILIMF_NO_ERROR
)
1566 r
= mailimf_header_string_write(f
, col
,
1567 comments
->cm_value
, strlen(comments
->cm_value
));
1568 if (r
!= MAILIMF_NO_ERROR
)
1571 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1572 if (r
!= MAILIMF_NO_ERROR
)
1578 return MAILIMF_NO_ERROR
;
1581 static int mailimf_optional_field_write(FILE * f
, int * col
,
1582 struct mailimf_optional_field
* field
)
1586 if (strlen(field
->fld_name
) + 2 > MAX_VALID_IMF_LINE
)
1587 return MAILIMF_ERROR_INVAL
;
1589 r
= mailimf_string_write(f
, col
, field
->fld_name
, strlen(field
->fld_name
));
1590 if (r
!= MAILIMF_NO_ERROR
)
1593 r
= mailimf_string_write(f
, col
, ": ", 2);
1594 if (r
!= MAILIMF_NO_ERROR
)
1597 r
= mailimf_header_string_write(f
, col
, field
->fld_value
,
1598 strlen(field
->fld_value
));
1599 if (r
!= MAILIMF_NO_ERROR
)
1603 /* XXX parsing debug */
1604 mailimf_string_write(f
, col
, " (X)", 4);
1607 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1608 if (r
!= MAILIMF_NO_ERROR
)
1614 return MAILIMF_NO_ERROR
;
1617 static int mailimf_keywords_write(FILE * f
, int * col
,
1618 struct mailimf_keywords
* keywords
)
1624 r
= mailimf_string_write(f
, col
, "Keywords: ", 10);
1625 if (r
!= MAILIMF_NO_ERROR
)
1630 for(cur
= clist_begin(keywords
->kw_list
) ; cur
!= NULL
;
1631 cur
= clist_next(cur
)) {
1635 keyword
= clist_content(cur
);
1636 len
= strlen(keyword
);
1639 r
= mailimf_string_write(f
, col
, ", ", 2);
1640 if (r
!= MAILIMF_NO_ERROR
)
1650 if (* col
+ len
>= MAX_MAIL_COL
) {
1651 r
= mailimf_string_write(f
, col
, "\r\n ", 3);
1652 if (r
!= MAILIMF_NO_ERROR
)
1661 r
= mailimf_header_string_write(f
, col
, keyword
, len
);
1662 if (r
!= MAILIMF_NO_ERROR
)
1666 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1667 if (r
!= MAILIMF_NO_ERROR
)
1673 return MAILIMF_NO_ERROR
;
1677 static int mailimf_delivering_info_write(FILE * f
, int * col
,
1678 struct mailimf_delivering_info
* info
)
1683 for(cur
= clist_begin(info
->received_fields
) ;
1684 cur
!= NULL
; cur
= cur
->next
) {
1685 struct mailimf_trace_resent_fields
* field
;
1689 r
= mailimf_trace_resent_fields_write(f
, col
, field
);
1690 if (r
!= MAILIMF_NO_ERROR
)
1694 return MAILIMF_NO_ERROR
;
1699 mailimf_trace_resent_fields_write(FILE * f
, int * col
,
1700 struct mailimf_trace_resent_fields
* field
)
1704 if (field
->return_path
!= NULL
) {
1705 r
= mailimf_return_write(f
, col
, field
->return_path
);
1706 if (r
!= MAILIMF_NO_ERROR
)
1710 if (field
->resent_fields
!= NULL
) {
1711 r
= mailimf_resent_fields_write(f
, col
, field
->resent_fields
);
1712 if (r
!= MAILIMF_NO_ERROR
)
1716 return MAILIMF_NO_ERROR
;
1720 static int mailimf_return_write(FILE * f
, int * col
,
1721 struct mailimf_return
* return_path
)
1725 r
= mailimf_string_write(f
, col
, "Return-Path: ", 13);
1726 if (r
!= MAILIMF_NO_ERROR
)
1729 r
= mailimf_path_write(f
, col
, return_path
->ret_path
);
1730 if (r
!= MAILIMF_NO_ERROR
)
1733 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1734 if (r
!= MAILIMF_NO_ERROR
)
1740 return MAILIMF_NO_ERROR
;
1743 static int mailimf_path_write(FILE * f
, int * col
,
1744 struct mailimf_path
* path
)
1748 r
= mailimf_string_write(f
, col
, "<", 1);
1749 if (r
!= MAILIMF_NO_ERROR
)
1752 r
= mailimf_string_write(f
, col
, path
->pt_addr_spec
,
1753 strlen(path
->pt_addr_spec
));
1754 if (r
!= MAILIMF_NO_ERROR
)
1757 r
= mailimf_string_write(f
, col
, ">", 1);
1758 if (r
!= MAILIMF_NO_ERROR
)
1761 return MAILIMF_NO_ERROR
;
1765 static int mailimf_resent_fields_write(FILE * f
, int * col
,
1766 struct mailimf_resent_fields_list
*
1772 for(cur
= clist_begin(resent_fields
->list
) ; cur
!= NULL
; cur
= cur
->next
) {
1773 struct mailimf_resent_field
* field
;
1777 r
= mailimf_resent_field_write(f
, col
, field
);
1778 if (r
!= MAILIMF_NO_ERROR
)
1782 return MAILIMF_NO_ERROR
;
1787 static int mailimf_resent_field_write(FILE * f
, int * col
,
1788 struct mailimf_resent_field
*
1793 switch (resent_field
->type
) {
1794 case MAILIMF_RESENT_FIELD_DATE
:
1795 r
= mailimf_resent_date_write(f
, col
, resent_field
->resent_date
);
1798 case MAILIMF_RESENT_FIELD_FROM
:
1799 r
= mailimf_resent_from_write(f
, col
, resent_field
->resent_from
);
1802 case MAILIMF_RESENT_FIELD_SENDER
:
1803 r
= mailimf_resent_sender_write(f
, col
, resent_field
->resent_sender
);
1806 case MAILIMF_RESENT_FIELD_TO
:
1807 r
= mailimf_resent_to_write(f
, col
, resent_field
->resent_to
);
1810 case MAILIMF_RESENT_FIELD_CC
:
1811 r
= mailimf_resent_cc_write(f
, col
, resent_field
->resent_cc
);
1814 case MAILIMF_RESENT_FIELD_BCC
:
1815 r
= mailimf_resent_bcc_write(f
, col
, resent_field
->resent_bcc
);
1818 case MAILIMF_RESENT_FIELD_MSG_ID
:
1819 r
= mailimf_resent_msg_id_write(f
, col
, resent_field
->resent_msg_id
);
1822 r
= MAILIMF_ERROR_INVAL
;
1827 if (r
!= MAILIMF_NO_ERROR
)
1830 return MAILIMF_NO_ERROR
;
1834 static int mailimf_resent_date_write(FILE * f
, int * col
,
1835 struct mailimf_orig_date
* date
)
1839 r
= mailimf_string_write(f
, col
, "Resent-Date: ", 13);
1840 if (r
!= MAILIMF_NO_ERROR
)
1843 r
= mailimf_date_time_write(f
, col
, date
->dt_date_time
);
1844 if (r
!= MAILIMF_NO_ERROR
)
1847 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1848 if (r
!= MAILIMF_NO_ERROR
)
1854 return MAILIMF_NO_ERROR
;
1857 static int mailimf_resent_from_write(FILE * f
, int * col
,
1858 struct mailimf_from
* from
)
1862 r
= mailimf_string_write(f
, col
, "Resent-From: ", 13);
1863 if (r
!= MAILIMF_NO_ERROR
)
1866 r
= mailimf_mailbox_list_write(f
, col
, from
->frm_mb_list
);
1867 if (r
!= MAILIMF_NO_ERROR
)
1870 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1871 if (r
!= MAILIMF_NO_ERROR
)
1877 return MAILIMF_NO_ERROR
;
1880 static int mailimf_resent_sender_write(FILE * f
, int * col
,
1881 struct mailimf_sender
* sender
)
1885 r
= mailimf_string_write(f
, col
, "Resent-Sender: ", 15);
1886 if (r
!= MAILIMF_NO_ERROR
)
1889 r
= mailimf_mailbox_write(f
, col
, sender
->snd_mb
);
1890 if (r
!= MAILIMF_NO_ERROR
)
1893 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1894 if (r
!= MAILIMF_NO_ERROR
)
1900 return MAILIMF_NO_ERROR
;
1903 static int mailimf_resent_to_write(FILE * f
, int * col
,
1904 struct mailimf_to
* to
)
1908 r
= mailimf_string_write(f
, col
, "Resent-To: ", 11);
1909 if (r
!= MAILIMF_NO_ERROR
)
1912 r
= mailimf_address_list_write(f
, col
, to
->to_addr_list
);
1913 if (r
!= MAILIMF_NO_ERROR
)
1916 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1917 if (r
!= MAILIMF_NO_ERROR
)
1923 return MAILIMF_NO_ERROR
;
1927 static int mailimf_resent_cc_write(FILE * f
, int * col
,
1928 struct mailimf_cc
* cc
)
1932 r
= mailimf_string_write(f
, col
, "Resent-Cc: ", 11);
1933 if (r
!= MAILIMF_NO_ERROR
)
1936 r
= mailimf_address_list_write(f
, col
, cc
->cc_addr_list
);
1937 if (r
!= MAILIMF_NO_ERROR
)
1940 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1941 if (r
!= MAILIMF_NO_ERROR
)
1947 return MAILIMF_NO_ERROR
;
1951 static int mailimf_resent_bcc_write(FILE * f
, int * col
,
1952 struct mailimf_bcc
* bcc
)
1956 r
= mailimf_string_write(f
, col
, "Resent-Bcc: ", 12);
1957 if (r
!= MAILIMF_NO_ERROR
)
1960 if (bcc
->bcc_addr_list
!= NULL
) {
1961 r
= mailimf_address_list_write(f
, col
, bcc
->bcc_addr_list
);
1962 if (r
!= MAILIMF_NO_ERROR
)
1966 r
= mailimf_string_write(f
, col
, "\r\n", 2);
1967 if (r
!= MAILIMF_NO_ERROR
)
1973 return MAILIMF_NO_ERROR
;
1978 mailimf_resent_msg_id_write(FILE * f
, int * col
,
1979 struct mailimf_message_id
* message_id
)
1983 r
= mailimf_string_write(f
, col
, "Resent-Message-ID: ", 19);
1984 if (r
!= MAILIMF_NO_ERROR
)
1987 r
= mailimf_string_write(f
, col
, "<", 1);
1988 if (r
!= MAILIMF_NO_ERROR
)
1991 r
= mailimf_string_write(f
, col
,
1992 message_id
->mid_value
, strlen(message_id
->mid_value
));
1993 if (r
!= MAILIMF_NO_ERROR
)
1996 r
= mailimf_string_write(f
, col
, ">", 1);
1997 if (r
!= MAILIMF_NO_ERROR
)
2000 r
= mailimf_string_write(f
, col
, "\r\n", 2);
2001 if (r
!= MAILIMF_NO_ERROR
)
2007 return MAILIMF_NO_ERROR
;