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
36 #include "mailimf_write.h"
42 #define MAX_MAIL_COL 72
52 #define MAX_VALID_IMF_LINE 998
54 static int mailimf_orig_date_write(FILE * f, int * col,
55 struct mailimf_orig_date * date);
56 static int mailimf_date_time_write(FILE * f, int * col,
57 struct mailimf_date_time * date_time);
58 static int mailimf_from_write(FILE * f, int * col,
59 struct mailimf_from * from);
60 static int mailimf_sender_write(FILE * f, int * col,
61 struct mailimf_sender * sender);
62 static int mailimf_reply_to_write(FILE * f, int * col,
63 struct mailimf_reply_to * reply_to);
64 static int mailimf_to_write(FILE * f, int * col,
65 struct mailimf_to * to);
66 static int mailimf_cc_write(FILE * f, int * col,
67 struct mailimf_cc * to);
68 static int mailimf_bcc_write(FILE * f, int * col,
69 struct mailimf_bcc * to);
70 static int mailimf_message_id_write(FILE * f, int * col,
71 struct mailimf_message_id * message_id);
72 static int mailimf_msg_id_list_write(FILE * f, int * col,
74 static int mailimf_in_reply_to_write(FILE * f, int * col,
75 struct mailimf_in_reply_to *
77 static int mailimf_references_write(FILE * f, int * col,
78 struct mailimf_references * references);
79 static int mailimf_subject_write(FILE * f, int * col,
80 struct mailimf_subject * subject);
82 static int mailimf_address_write(FILE * f, int * col,
83 struct mailimf_address * addr);
84 static int mailimf_group_write(FILE * f, int * col,
85 struct mailimf_group * group);
87 static int mailimf_mailbox_write(FILE * f, int * col,
88 struct mailimf_mailbox * mb);
90 static int mailimf_comments_write(FILE * f, int * col,
91 struct mailimf_comments * comments);
93 static int mailimf_optional_field_write(FILE * f, int * col,
94 struct mailimf_optional_field * field);
96 static int mailimf_keywords_write(FILE * f, int * col,
97 struct mailimf_keywords * keywords);
99 static int mailimf_return_write(FILE * f, int * col,
100 struct mailimf_return * return_path);
102 static int mailimf_path_write(FILE * f, int * col,
103 struct mailimf_path * path);
105 static int mailimf_resent_date_write(FILE * f, int * col,
106 struct mailimf_orig_date * date);
108 static int mailimf_resent_from_write(FILE * f, int * col,
109 struct mailimf_from * from);
111 static int mailimf_resent_sender_write(FILE * f, int * col,
112 struct mailimf_sender * sender);
114 static int mailimf_resent_to_write(FILE * f, int * col,
115 struct mailimf_to * to);
117 static int mailimf_resent_cc_write(FILE * f, int * col,
118 struct mailimf_cc * cc);
120 static int mailimf_resent_bcc_write(FILE * f, int * col,
121 struct mailimf_bcc * bcc);
124 mailimf_resent_msg_id_write(FILE * f, int * col,
125 struct mailimf_message_id * message_id);
129 /* ************************ */
132 int mailimf_string_write(FILE * f, int * col,
133 char * str, size_t length)
138 r = fwrite(str, sizeof(char), length, f);
140 return MAILIMF_ERROR_FILE;
144 return MAILIMF_NO_ERROR;
149 #define HEADER_FOLD "\r\n "
151 static inline int flush_buf(FILE * f, const char * str, size_t length)
156 r = fwrite(str, 1, length, f);
158 return MAILIMF_ERROR_FILE;
160 return MAILIMF_NO_ERROR;
163 #define CUT_AT_MAX_VALID_IMF_LINE
165 int mailimf_string_write(FILE * f, int * col,
166 const char * str, size_t length)
170 const char * block_begin;
179 #ifdef CUT_AT_MAX_VALID_IMF_LINE
182 cut lines at maximum valid length for internet message
183 format standard (currently RFC 2822)
185 This should not happen.
186 In case there are some lines larger than 998 in body,
187 the encoding must be changed into base64 or quoted-printable
188 so that wrapping to 72 columns is done.
191 r = flush_buf(f, block_begin, count);
192 if (r != MAILIMF_NO_ERROR)
195 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
197 return MAILIMF_ERROR_FILE;
207 r = flush_buf(f, block_begin, count);
208 if (r != MAILIMF_NO_ERROR)
211 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
213 return MAILIMF_ERROR_FILE;
226 if (* (p + 1) == '\n') {
227 r = flush_buf(f, block_begin, count);
228 if (r != MAILIMF_NO_ERROR)
231 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
233 return MAILIMF_ERROR_FILE;
246 r = flush_buf(f, block_begin, count);
247 if (r != MAILIMF_NO_ERROR)
250 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
252 return MAILIMF_ERROR_FILE;
271 r = flush_buf(f, block_begin, count);
272 if (r != MAILIMF_NO_ERROR)
276 return MAILIMF_NO_ERROR;
280 int mailimf_header_string_write(FILE * f, int * col,
281 char * str, size_t length)
290 if (* col + length < MAX_MAIL_COL)
291 return mailimf_string_write(f, col, str, length);
296 last_cut = block_begin;
300 if (current_col >= MAX_MAIL_COL) {
301 /* if we reach the maximum recommanded size of line */
302 if (last_cut == block_begin) {
303 /* if we could not find any place to cut */
305 /* fold the header */
306 r = mailimf_string_write(f, col, HEADER_FOLD,
307 sizeof(HEADER_FOLD) - 1);
308 if (r != MAILIMF_NO_ERROR)
310 current_col = * col + p - block_begin;
315 r = mailimf_string_write(f, col, block_begin, p - block_begin);
316 if (r != MAILIMF_NO_ERROR)
318 r = mailimf_string_write(f, col, HEADER_FOLD,
319 sizeof(HEADER_FOLD) - 1);
320 if (r != MAILIMF_NO_ERROR)
324 last_cut = block_begin;
325 current_col = * col + p - block_begin;
329 /* if we found a place to cut */
330 r = mailimf_string_write(f, col, block_begin, last_cut - block_begin);
331 if (r != MAILIMF_NO_ERROR)
333 r = mailimf_string_write(f, col, HEADER_FOLD,
334 sizeof(HEADER_FOLD) - 1);
335 if (r != MAILIMF_NO_ERROR)
338 block_begin = last_cut;
339 last_cut = block_begin;
340 current_col = * col + p - block_begin;
370 return mailimf_string_write(f, col, block_begin, p - block_begin);
383 int mailimf_header_string_write(FILE * f, int * col,
384 const char * str, size_t length)
388 const char * block_begin;
393 if (* col < MAX_MAIL_COL)
394 state = STATE_LOWER_72_CUT;
395 else if (* col == MAX_MAIL_COL)
396 state = STATE_EQUAL_72;
397 else if (* col < MAX_VALID_IMF_LINE)
398 state = STATE_LOWER_998;
400 state = STATE_EQUAL_998;
424 state = STATE_LOWER_72_CUT;
428 if (size < MAX_MAIL_COL - 1) {
434 state = STATE_EQUAL_72;
441 break; /* end of STATE_LOWER_72 */
443 case STATE_LOWER_72_CUT:
450 state = STATE_LOWER_72;
462 if (size < MAX_MAIL_COL) {
468 r = mailimf_string_write(f, col, block_begin, cut - block_begin);
469 if (r != MAILIMF_NO_ERROR)
471 r = mailimf_string_write(f, col, HEADER_FOLD,
472 sizeof(HEADER_FOLD) - 1);
473 if (r != MAILIMF_NO_ERROR)
478 if ((* block_begin == ' ') || (* block_begin == '\t'))
480 size = p - block_begin + * col;
481 state = STATE_LOWER_72;
485 break; /* end of STATE_LOWER_72_CUT */
494 state = STATE_LOWER_72;
499 r = mailimf_string_write(f, col, block_begin, p - block_begin);
500 if (r != MAILIMF_NO_ERROR)
502 r = mailimf_string_write(f, col, HEADER_FOLD,
503 sizeof(HEADER_FOLD) - 1);
504 if (r != MAILIMF_NO_ERROR)
509 size = p - block_begin + * col;
510 state = STATE_LOWER_72;
517 state = STATE_LOWER_998;
520 break; /* end of STATE_EQUAL_72 */
522 case STATE_LOWER_998:
529 state = STATE_LOWER_72;
534 r = mailimf_string_write(f, col, block_begin, p - block_begin);
535 if (r != MAILIMF_NO_ERROR)
537 r = mailimf_string_write(f, col, HEADER_FOLD,
538 sizeof(HEADER_FOLD) - 1);
539 if (r != MAILIMF_NO_ERROR)
544 size = p - block_begin + * col;
545 state = STATE_LOWER_72;
549 if (size < MAX_VALID_IMF_LINE - 1) {
558 state = STATE_EQUAL_998;
562 break; /* end of STATE_LOWER_998 */
564 case STATE_EQUAL_998:
571 state = STATE_LOWER_72;
576 r = mailimf_string_write(f, col, block_begin, p - block_begin);
577 if (r != MAILIMF_NO_ERROR)
579 r = mailimf_string_write(f, col, HEADER_FOLD,
580 sizeof(HEADER_FOLD) - 1);
581 if (r != MAILIMF_NO_ERROR)
586 size = p - block_begin + * col;
587 state = STATE_LOWER_72;
591 #ifdef CUT_AT_MAX_VALID_IMF_LINE
592 r = mailimf_string_write(f, col, block_begin, p - block_begin);
593 if (r != MAILIMF_NO_ERROR)
595 r = mailimf_string_write(f, col, HEADER_FOLD,
596 sizeof(HEADER_FOLD) - 1);
597 if (r != MAILIMF_NO_ERROR)
602 size = p - block_begin + * col;
603 state = STATE_LOWER_72;
611 break; /* end of STATE_EQUAL_998 */
615 r = mailimf_string_write(f, col, block_begin, p - block_begin);
616 if (r != MAILIMF_NO_ERROR)
619 return MAILIMF_NO_ERROR;
629 int mailimf_header_string_write(FILE * f, int * col,
630 const char * str, size_t length)
634 const char * word_begin;
685 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
686 mailimf_string_write(f, col, HEADER_FOLD,
687 sizeof(HEADER_FOLD) - 1);
690 mailimf_string_write(f, col, " ", 1);
693 mailimf_string_write(f, col, word_begin, p - word_begin);
698 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
699 mailimf_string_write(f, col, word_begin, p - word_begin);
700 mailimf_string_write(f, col, HEADER_FOLD,
701 sizeof(HEADER_FOLD) - 1);
712 if (state == STATE_WORD) {
713 if (p - word_begin + (* col) >= MAX_MAIL_COL)
714 mailimf_string_write(f, col, HEADER_FOLD,
715 sizeof(HEADER_FOLD) - 1);
718 mailimf_string_write(f, col, " ", 1);
721 mailimf_string_write(f, col, word_begin, p - word_begin);
724 return MAILIMF_NO_ERROR;
727 int mailimf_envelope_fields_write(FILE * f, int * col,
728 struct mailimf_fields * fields)
732 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
733 cur = clist_next(cur)) {
735 struct mailimf_field * field;
737 field = clist_content(cur);
738 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
739 r = mailimf_field_write(f, col, field);
740 if (r != MAILIMF_NO_ERROR)
745 return MAILIMF_NO_ERROR;
748 int mailimf_fields_write(FILE * f, int * col,
749 struct mailimf_fields * fields)
753 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
754 cur = clist_next(cur)) {
757 r = mailimf_field_write(f, col, clist_content(cur));
758 if (r != MAILIMF_NO_ERROR)
762 return MAILIMF_NO_ERROR;
766 int mailimf_unparsed_fields_write(FILE * f, int * col,
767 struct mailimf_unparsed_fields * fields)
771 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
774 r = mailimf_optional_field_write(f, col, cur->data);
775 if (r != MAILIMF_NO_ERROR)
779 return MAILIMF_NO_ERROR;
783 int mailimf_field_write(FILE * f, int * col,
784 struct mailimf_field * field)
788 switch (field->fld_type) {
789 case MAILIMF_FIELD_RETURN_PATH:
790 r = mailimf_return_write(f, col, field->fld_data.fld_return_path);
792 case MAILIMF_FIELD_RESENT_DATE:
793 r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date);
795 case MAILIMF_FIELD_RESENT_FROM:
796 r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from);
798 case MAILIMF_FIELD_RESENT_SENDER:
799 r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender);
801 case MAILIMF_FIELD_RESENT_TO:
802 r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to);
804 case MAILIMF_FIELD_RESENT_CC:
805 r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc);
807 case MAILIMF_FIELD_RESENT_BCC:
808 r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc);
810 case MAILIMF_FIELD_RESENT_MSG_ID:
811 r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id);
813 case MAILIMF_FIELD_ORIG_DATE:
814 r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date);
816 case MAILIMF_FIELD_FROM:
817 r = mailimf_from_write(f, col, field->fld_data.fld_from);
819 case MAILIMF_FIELD_SENDER:
820 r = mailimf_sender_write(f, col, field->fld_data.fld_sender);
822 case MAILIMF_FIELD_REPLY_TO:
823 r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to);
825 case MAILIMF_FIELD_TO:
826 r = mailimf_to_write(f, col, field->fld_data.fld_to);
828 case MAILIMF_FIELD_CC:
829 r = mailimf_cc_write(f, col, field->fld_data.fld_cc);
831 case MAILIMF_FIELD_BCC:
832 r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc);
834 case MAILIMF_FIELD_MESSAGE_ID:
835 r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id);
837 case MAILIMF_FIELD_IN_REPLY_TO:
838 r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to);
840 case MAILIMF_FIELD_REFERENCES:
841 r = mailimf_references_write(f, col, field->fld_data.fld_references);
843 case MAILIMF_FIELD_SUBJECT:
844 r = mailimf_subject_write(f, col, field->fld_data.fld_subject);
846 case MAILIMF_FIELD_COMMENTS:
847 r = mailimf_comments_write(f, col, field->fld_data.fld_comments);
849 case MAILIMF_FIELD_KEYWORDS:
850 r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords);
852 case MAILIMF_FIELD_OPTIONAL_FIELD:
853 r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field);
856 r = MAILIMF_ERROR_INVAL;
860 if (r != MAILIMF_NO_ERROR)
863 return MAILIMF_NO_ERROR;
867 static int mailimf_orig_date_write(FILE * f, int * col,
868 struct mailimf_orig_date * date)
872 r = mailimf_string_write(f, col, "Date: ", 6);
873 if (r != MAILIMF_NO_ERROR)
876 r = mailimf_date_time_write(f, col, date->dt_date_time);
877 if (r != MAILIMF_NO_ERROR)
880 r = mailimf_string_write(f, col, "\r\n", 2);
881 if (r != MAILIMF_NO_ERROR)
887 return MAILIMF_NO_ERROR;
890 #define MAX_DATE_STR 256
895 static int dayofweek(int year, int month, int day)
897 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
901 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
904 static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
906 static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
907 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
909 static int mailimf_date_time_write(FILE * f, int * col,
910 struct mailimf_date_time * date_time)
913 char date_str[MAX_DATE_STR];
921 tmval.tm_sec = date_time->sec;
922 tmval.tm_min = date_time->min;
923 tmval.tm_hour = date_time->hour;
924 tmval.tm_sec = date_time->sec;
925 tmval.tm_mday = date_time->day;
926 tmval.tm_mon = date_time->month - 1;
927 tmval.tm_year = date_time->year - 1900;
930 timeval = mktime(&tmval);
932 localtime_r(&timeval, &tmval);
935 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
937 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
938 week_of_day_str[wday], date_time->dt_day,
939 month_str[date_time->dt_month - 1],
940 date_time->dt_year, date_time->dt_hour,
941 date_time->dt_min, date_time->dt_sec,
944 r = mailimf_string_write(f, col, date_str, strlen(date_str));
946 if (r != MAILIMF_NO_ERROR)
949 return MAILIMF_NO_ERROR;
952 static int mailimf_from_write(FILE * f, int * col,
953 struct mailimf_from * from)
957 r = mailimf_string_write(f, col, "From: ", 6);
958 if (r != MAILIMF_NO_ERROR)
961 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
962 if (r != MAILIMF_NO_ERROR)
965 r = mailimf_string_write(f, col, "\r\n", 2);
966 if (r != MAILIMF_NO_ERROR)
972 return MAILIMF_NO_ERROR;
975 static int mailimf_sender_write(FILE * f, int * col,
976 struct mailimf_sender * sender)
980 r = mailimf_string_write(f, col, "Sender: ", 8);
981 if (r != MAILIMF_NO_ERROR)
984 r = mailimf_mailbox_write(f, col, sender->snd_mb);
985 if (r != MAILIMF_NO_ERROR)
988 r = mailimf_string_write(f, col, "\r\n", 2);
989 if (r != MAILIMF_NO_ERROR)
995 return MAILIMF_NO_ERROR;
998 static int mailimf_reply_to_write(FILE * f, int * col,
999 struct mailimf_reply_to * reply_to)
1003 r = mailimf_string_write(f, col, "Reply-To: ", 10);
1004 if (r != MAILIMF_NO_ERROR)
1007 r = mailimf_address_list_write(f, col, reply_to->rt_addr_list);
1008 if (r != MAILIMF_NO_ERROR)
1011 r = mailimf_string_write(f, col, "\r\n", 2);
1012 if (r != MAILIMF_NO_ERROR)
1018 return MAILIMF_NO_ERROR;
1022 static int mailimf_to_write(FILE * f, int * col,
1023 struct mailimf_to * to)
1027 r = mailimf_string_write(f, col, "To: ", 4);
1028 if (r != MAILIMF_NO_ERROR)
1031 r = mailimf_address_list_write(f, col, to->to_addr_list);
1032 if (r != MAILIMF_NO_ERROR)
1035 r = mailimf_string_write(f, col, "\r\n", 2);
1036 if (r != MAILIMF_NO_ERROR)
1042 return MAILIMF_NO_ERROR;
1046 static int mailimf_cc_write(FILE * f, int * col,
1047 struct mailimf_cc * cc)
1051 r = mailimf_string_write(f, col, "Cc: ", 4);
1052 if (r != MAILIMF_NO_ERROR)
1055 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1056 if (r != MAILIMF_NO_ERROR)
1059 r = mailimf_string_write(f, col, "\r\n", 2);
1060 if (r != MAILIMF_NO_ERROR)
1066 return MAILIMF_NO_ERROR;
1070 static int mailimf_bcc_write(FILE * f, int * col,
1071 struct mailimf_bcc * bcc)
1075 r = mailimf_string_write(f, col, "Bcc: ", 5);
1076 if (r != MAILIMF_NO_ERROR)
1079 if (bcc->bcc_addr_list != NULL) {
1080 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1081 if (r != MAILIMF_NO_ERROR)
1085 r = mailimf_string_write(f, col, "\r\n", 2);
1086 if (r != MAILIMF_NO_ERROR)
1092 return MAILIMF_NO_ERROR;
1096 static int mailimf_message_id_write(FILE * f, int * col,
1097 struct mailimf_message_id * message_id)
1101 r = mailimf_string_write(f, col, "Message-ID: ", 12);
1102 if (r != MAILIMF_NO_ERROR)
1105 r = mailimf_string_write(f, col, "<", 1);
1106 if (r != MAILIMF_NO_ERROR)
1109 r = mailimf_string_write(f, col,
1110 message_id->mid_value,
1111 strlen(message_id->mid_value));
1112 if (r != MAILIMF_NO_ERROR)
1115 r = mailimf_string_write(f, col, ">", 1);
1116 if (r != MAILIMF_NO_ERROR)
1119 r = mailimf_string_write(f, col, "\r\n", 2);
1120 if (r != MAILIMF_NO_ERROR)
1126 return MAILIMF_NO_ERROR;
1130 static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list)
1138 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1142 msgid = clist_content(cur);
1143 len = strlen(msgid);
1146 XXX - if this is the first message ID, don't fold.
1147 This is a workaround for a bug of old versions of INN.
1152 if (* col + len >= MAX_MAIL_COL) {
1153 r = mailimf_string_write(f, col, "\r\n ", 3);
1154 if (r != MAILIMF_NO_ERROR)
1165 r = mailimf_string_write(f, col, " ", 1);
1166 if (r != MAILIMF_NO_ERROR)
1173 r = mailimf_string_write(f, col, "<", 1);
1174 if (r != MAILIMF_NO_ERROR)
1177 r = mailimf_string_write(f, col, msgid, len);
1178 if (r != MAILIMF_NO_ERROR)
1181 r = mailimf_string_write(f, col, ">", 1);
1182 if (r != MAILIMF_NO_ERROR)
1186 return MAILIMF_NO_ERROR;
1190 static int mailimf_in_reply_to_write(FILE * f, int * col,
1191 struct mailimf_in_reply_to * in_reply_to)
1195 r = mailimf_string_write(f, col, "In-Reply-To: ", 13);
1196 if (r != MAILIMF_NO_ERROR)
1199 r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list);
1200 if (r != MAILIMF_NO_ERROR)
1203 r = mailimf_string_write(f, col, "\r\n", 2);
1204 if (r != MAILIMF_NO_ERROR)
1210 return MAILIMF_NO_ERROR;
1214 static int mailimf_references_write(FILE * f, int * col,
1215 struct mailimf_references * references)
1219 r = mailimf_string_write(f, col, "References: ", 12);
1220 if (r != MAILIMF_NO_ERROR)
1223 r = mailimf_msg_id_list_write(f, col, references->mid_list);
1224 if (r != MAILIMF_NO_ERROR)
1227 r = mailimf_string_write(f, col, "\r\n", 2);
1228 if (r != MAILIMF_NO_ERROR)
1234 return MAILIMF_NO_ERROR;
1239 static int mailimf_subject_write(FILE * f, int * col,
1240 struct mailimf_subject * subject)
1244 r = mailimf_string_write(f, col, "Subject: ", 9);
1245 if (r != MAILIMF_NO_ERROR)
1248 r = mailimf_header_string_write(f, col,
1249 subject->sbj_value, strlen(subject->sbj_value));
1250 if (r != MAILIMF_NO_ERROR)
1253 r = mailimf_string_write(f, col, "\r\n", 2);
1254 if (r != MAILIMF_NO_ERROR)
1260 return MAILIMF_NO_ERROR;
1263 int mailimf_address_list_write(FILE * f, int * col,
1264 struct mailimf_address_list * addr_list)
1272 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1273 cur = clist_next(cur)) {
1274 struct mailimf_address * addr;
1276 addr = clist_content(cur);
1279 r = mailimf_string_write(f, col, ", ", 2);
1280 if (r != MAILIMF_NO_ERROR)
1287 r = mailimf_address_write(f, col, addr);
1288 if (r != MAILIMF_NO_ERROR)
1292 return MAILIMF_NO_ERROR;
1296 static int mailimf_address_write(FILE * f, int * col,
1297 struct mailimf_address * addr)
1301 switch(addr->ad_type) {
1302 case MAILIMF_ADDRESS_MAILBOX:
1303 r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox);
1304 if (r != MAILIMF_NO_ERROR)
1309 case MAILIMF_ADDRESS_GROUP:
1310 r = mailimf_group_write(f, col, addr->ad_data.ad_group);
1311 if (r != MAILIMF_NO_ERROR)
1317 return MAILIMF_NO_ERROR;
1321 static int mailimf_group_write(FILE * f, int * col,
1322 struct mailimf_group * group)
1326 r = mailimf_header_string_write(f, col, group->grp_display_name,
1327 strlen(group->grp_display_name));
1328 if (r != MAILIMF_NO_ERROR)
1331 r = mailimf_string_write(f, col, ": ", 2);
1332 if (r != MAILIMF_NO_ERROR)
1335 if (group->grp_mb_list != NULL) {
1336 r = mailimf_mailbox_list_write(f, col, group->grp_mb_list);
1337 if (r != MAILIMF_NO_ERROR)
1341 r = mailimf_string_write(f, col, ";", 1);
1342 if (r != MAILIMF_NO_ERROR)
1345 return MAILIMF_NO_ERROR;
1349 int mailimf_mailbox_list_write(FILE * f, int * col,
1350 struct mailimf_mailbox_list * mb_list)
1358 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1359 cur = clist_next(cur)) {
1360 struct mailimf_mailbox * mb;
1362 mb = clist_content(cur);
1365 r = mailimf_string_write(f, col, ", ", 2);
1366 if (r != MAILIMF_NO_ERROR)
1373 r = mailimf_mailbox_write(f, col, mb);
1374 if (r != MAILIMF_NO_ERROR)
1378 return MAILIMF_NO_ERROR;
1382 int mailimf_quoted_string_write(FILE * f, int * col,
1383 const char * string, size_t len)
1389 for(i = 0 ; i < len ; i ++) {
1390 switch (string[i]) {
1395 return MAILIMF_ERROR_FILE;
1396 r = fputc(string[i], f);
1398 return MAILIMF_ERROR_FILE;
1403 r = fputc(string[i], f);
1405 return MAILIMF_ERROR_FILE;
1412 return MAILIMF_NO_ERROR;
1418 atext = ALPHA / DIGIT / ; Any character except controls,
1419 "!" / "#" / ; SP, and specials.
1420 "$" / "%" / ; Used for atoms
1431 static int is_atext(const char * s)
1435 for(p = s ; * p != 0 ; p ++) {
1436 if (isalpha((unsigned char) * p))
1438 if (isdigit((unsigned char) * p))
1471 static int mailimf_mailbox_write(FILE * f, int * col,
1472 struct mailimf_mailbox * mb)
1480 if (mb->mb_display_name != NULL) {
1481 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1482 r = mailimf_string_write(f, col, "\r\n ", 3);
1483 if (r != MAILIMF_NO_ERROR)
1493 if (mb->mb_display_name) {
1495 if (is_atext(mb->mb_display_name)) {
1496 r = mailimf_header_string_write(f, col, mb->mb_display_name,
1497 strlen(mb->mb_display_name));
1498 if (r != MAILIMF_NO_ERROR)
1502 if (mb->mb_display_name != NULL) {
1503 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1504 r = mailimf_string_write(f, col, "\r\n ", 3);
1505 if (r != MAILIMF_NO_ERROR)
1510 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1511 return MAILIMF_ERROR_INVAL;
1513 r = mailimf_quoted_string_write(f, col, mb->mb_display_name,
1514 strlen(mb->mb_display_name));
1515 if (r != MAILIMF_NO_ERROR)
1522 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1523 r = mailimf_string_write(f, col, "\r\n ", 3);
1524 if (r != MAILIMF_NO_ERROR)
1534 r = mailimf_string_write(f, col, "<", 1);
1536 r = mailimf_string_write(f, col, " <", 2);
1537 if (r != MAILIMF_NO_ERROR)
1540 r = mailimf_string_write(f, col, mb->mb_addr_spec,
1541 strlen(mb->mb_addr_spec));
1542 if (r != MAILIMF_NO_ERROR)
1545 r = mailimf_string_write(f, col, ">", 1);
1546 if (r != MAILIMF_NO_ERROR)
1550 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1551 r = mailimf_string_write(f, col, "\r\n ", 3);
1552 if (r != MAILIMF_NO_ERROR)
1556 r = mailimf_string_write(f, col,
1557 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1558 if (r != MAILIMF_NO_ERROR)
1563 return MAILIMF_NO_ERROR;
1566 static int mailimf_comments_write(FILE * f, int * col,
1567 struct mailimf_comments * comments)
1571 r = mailimf_string_write(f, col, "Comments: ", 10);
1572 if (r != MAILIMF_NO_ERROR)
1575 r = mailimf_header_string_write(f, col,
1576 comments->cm_value, strlen(comments->cm_value));
1577 if (r != MAILIMF_NO_ERROR)
1580 r = mailimf_string_write(f, col, "\r\n", 2);
1581 if (r != MAILIMF_NO_ERROR)
1587 return MAILIMF_NO_ERROR;
1590 static int mailimf_optional_field_write(FILE * f, int * col,
1591 struct mailimf_optional_field * field)
1595 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1596 return MAILIMF_ERROR_INVAL;
1598 r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name));
1599 if (r != MAILIMF_NO_ERROR)
1602 r = mailimf_string_write(f, col, ": ", 2);
1603 if (r != MAILIMF_NO_ERROR)
1606 r = mailimf_header_string_write(f, col, field->fld_value,
1607 strlen(field->fld_value));
1608 if (r != MAILIMF_NO_ERROR)
1612 /* XXX parsing debug */
1613 mailimf_string_write(f, col, " (X)", 4);
1616 r = mailimf_string_write(f, col, "\r\n", 2);
1617 if (r != MAILIMF_NO_ERROR)
1623 return MAILIMF_NO_ERROR;
1626 static int mailimf_keywords_write(FILE * f, int * col,
1627 struct mailimf_keywords * keywords)
1633 r = mailimf_string_write(f, col, "Keywords: ", 10);
1634 if (r != MAILIMF_NO_ERROR)
1639 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1640 cur = clist_next(cur)) {
1644 keyword = clist_content(cur);
1645 len = strlen(keyword);
1648 r = mailimf_string_write(f, col, ", ", 2);
1649 if (r != MAILIMF_NO_ERROR)
1659 if (* col + len >= MAX_MAIL_COL) {
1660 r = mailimf_string_write(f, col, "\r\n ", 3);
1661 if (r != MAILIMF_NO_ERROR)
1670 r = mailimf_header_string_write(f, col, keyword, len);
1671 if (r != MAILIMF_NO_ERROR)
1675 r = mailimf_string_write(f, col, "\r\n", 2);
1676 if (r != MAILIMF_NO_ERROR)
1682 return MAILIMF_NO_ERROR;
1686 static int mailimf_delivering_info_write(FILE * f, int * col,
1687 struct mailimf_delivering_info * info)
1692 for(cur = clist_begin(info->received_fields) ;
1693 cur != NULL ; cur = cur->next) {
1694 struct mailimf_trace_resent_fields * field;
1698 r = mailimf_trace_resent_fields_write(f, col, field);
1699 if (r != MAILIMF_NO_ERROR)
1703 return MAILIMF_NO_ERROR;
1708 mailimf_trace_resent_fields_write(FILE * f, int * col,
1709 struct mailimf_trace_resent_fields * field)
1713 if (field->return_path != NULL) {
1714 r = mailimf_return_write(f, col, field->return_path);
1715 if (r != MAILIMF_NO_ERROR)
1719 if (field->resent_fields != NULL) {
1720 r = mailimf_resent_fields_write(f, col, field->resent_fields);
1721 if (r != MAILIMF_NO_ERROR)
1725 return MAILIMF_NO_ERROR;
1729 static int mailimf_return_write(FILE * f, int * col,
1730 struct mailimf_return * return_path)
1734 r = mailimf_string_write(f, col, "Return-Path: ", 13);
1735 if (r != MAILIMF_NO_ERROR)
1738 r = mailimf_path_write(f, col, return_path->ret_path);
1739 if (r != MAILIMF_NO_ERROR)
1742 r = mailimf_string_write(f, col, "\r\n", 2);
1743 if (r != MAILIMF_NO_ERROR)
1749 return MAILIMF_NO_ERROR;
1752 static int mailimf_path_write(FILE * f, int * col,
1753 struct mailimf_path * path)
1757 r = mailimf_string_write(f, col, "<", 1);
1758 if (r != MAILIMF_NO_ERROR)
1761 r = mailimf_string_write(f, col, path->pt_addr_spec,
1762 strlen(path->pt_addr_spec));
1763 if (r != MAILIMF_NO_ERROR)
1766 r = mailimf_string_write(f, col, ">", 1);
1767 if (r != MAILIMF_NO_ERROR)
1770 return MAILIMF_NO_ERROR;
1774 static int mailimf_resent_fields_write(FILE * f, int * col,
1775 struct mailimf_resent_fields_list *
1781 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1782 struct mailimf_resent_field * field;
1786 r = mailimf_resent_field_write(f, col, field);
1787 if (r != MAILIMF_NO_ERROR)
1791 return MAILIMF_NO_ERROR;
1796 static int mailimf_resent_field_write(FILE * f, int * col,
1797 struct mailimf_resent_field *
1802 switch (resent_field->type) {
1803 case MAILIMF_RESENT_FIELD_DATE:
1804 r = mailimf_resent_date_write(f, col, resent_field->resent_date);
1807 case MAILIMF_RESENT_FIELD_FROM:
1808 r = mailimf_resent_from_write(f, col, resent_field->resent_from);
1811 case MAILIMF_RESENT_FIELD_SENDER:
1812 r = mailimf_resent_sender_write(f, col, resent_field->resent_sender);
1815 case MAILIMF_RESENT_FIELD_TO:
1816 r = mailimf_resent_to_write(f, col, resent_field->resent_to);
1819 case MAILIMF_RESENT_FIELD_CC:
1820 r = mailimf_resent_cc_write(f, col, resent_field->resent_cc);
1823 case MAILIMF_RESENT_FIELD_BCC:
1824 r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc);
1827 case MAILIMF_RESENT_FIELD_MSG_ID:
1828 r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id);
1831 r = MAILIMF_ERROR_INVAL;
1836 if (r != MAILIMF_NO_ERROR)
1839 return MAILIMF_NO_ERROR;
1843 static int mailimf_resent_date_write(FILE * f, int * col,
1844 struct mailimf_orig_date * date)
1848 r = mailimf_string_write(f, col, "Resent-Date: ", 13);
1849 if (r != MAILIMF_NO_ERROR)
1852 r = mailimf_date_time_write(f, col, date->dt_date_time);
1853 if (r != MAILIMF_NO_ERROR)
1856 r = mailimf_string_write(f, col, "\r\n", 2);
1857 if (r != MAILIMF_NO_ERROR)
1863 return MAILIMF_NO_ERROR;
1866 static int mailimf_resent_from_write(FILE * f, int * col,
1867 struct mailimf_from * from)
1871 r = mailimf_string_write(f, col, "Resent-From: ", 13);
1872 if (r != MAILIMF_NO_ERROR)
1875 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
1876 if (r != MAILIMF_NO_ERROR)
1879 r = mailimf_string_write(f, col, "\r\n", 2);
1880 if (r != MAILIMF_NO_ERROR)
1886 return MAILIMF_NO_ERROR;
1889 static int mailimf_resent_sender_write(FILE * f, int * col,
1890 struct mailimf_sender * sender)
1894 r = mailimf_string_write(f, col, "Resent-Sender: ", 15);
1895 if (r != MAILIMF_NO_ERROR)
1898 r = mailimf_mailbox_write(f, col, sender->snd_mb);
1899 if (r != MAILIMF_NO_ERROR)
1902 r = mailimf_string_write(f, col, "\r\n", 2);
1903 if (r != MAILIMF_NO_ERROR)
1909 return MAILIMF_NO_ERROR;
1912 static int mailimf_resent_to_write(FILE * f, int * col,
1913 struct mailimf_to * to)
1917 r = mailimf_string_write(f, col, "Resent-To: ", 11);
1918 if (r != MAILIMF_NO_ERROR)
1921 r = mailimf_address_list_write(f, col, to->to_addr_list);
1922 if (r != MAILIMF_NO_ERROR)
1925 r = mailimf_string_write(f, col, "\r\n", 2);
1926 if (r != MAILIMF_NO_ERROR)
1932 return MAILIMF_NO_ERROR;
1936 static int mailimf_resent_cc_write(FILE * f, int * col,
1937 struct mailimf_cc * cc)
1941 r = mailimf_string_write(f, col, "Resent-Cc: ", 11);
1942 if (r != MAILIMF_NO_ERROR)
1945 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1946 if (r != MAILIMF_NO_ERROR)
1949 r = mailimf_string_write(f, col, "\r\n", 2);
1950 if (r != MAILIMF_NO_ERROR)
1956 return MAILIMF_NO_ERROR;
1960 static int mailimf_resent_bcc_write(FILE * f, int * col,
1961 struct mailimf_bcc * bcc)
1965 r = mailimf_string_write(f, col, "Resent-Bcc: ", 12);
1966 if (r != MAILIMF_NO_ERROR)
1969 if (bcc->bcc_addr_list != NULL) {
1970 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1971 if (r != MAILIMF_NO_ERROR)
1975 r = mailimf_string_write(f, col, "\r\n", 2);
1976 if (r != MAILIMF_NO_ERROR)
1982 return MAILIMF_NO_ERROR;
1987 mailimf_resent_msg_id_write(FILE * f, int * col,
1988 struct mailimf_message_id * message_id)
1992 r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19);
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,
2001 message_id->mid_value, strlen(message_id->mid_value));
2002 if (r != MAILIMF_NO_ERROR)
2005 r = mailimf_string_write(f, col, ">", 1);
2006 if (r != MAILIMF_NO_ERROR)
2009 r = mailimf_string_write(f, col, "\r\n", 2);
2010 if (r != MAILIMF_NO_ERROR)
2016 return MAILIMF_NO_ERROR;