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;
635 const char * word_end;
636 const char * next_word;
689 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
690 mailimf_string_write(f, col, HEADER_FOLD,
691 sizeof(HEADER_FOLD) - 1);
694 mailimf_string_write(f, col, " ", 1);
697 mailimf_string_write(f, col, word_begin, p - word_begin);
702 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
703 mailimf_string_write(f, col, word_begin, p - word_begin);
704 mailimf_string_write(f, col, HEADER_FOLD,
705 sizeof(HEADER_FOLD) - 1);
716 if (state == STATE_WORD) {
717 if (p - word_begin + (* col) >= MAX_MAIL_COL)
718 mailimf_string_write(f, col, HEADER_FOLD,
719 sizeof(HEADER_FOLD) - 1);
722 mailimf_string_write(f, col, " ", 1);
725 mailimf_string_write(f, col, word_begin, p - word_begin);
728 return MAILIMF_NO_ERROR;
731 int mailimf_envelope_fields_write(FILE * f, int * col,
732 struct mailimf_fields * fields)
736 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
737 cur = clist_next(cur)) {
739 struct mailimf_field * field;
741 field = clist_content(cur);
742 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
743 r = mailimf_field_write(f, col, field);
744 if (r != MAILIMF_NO_ERROR)
749 return MAILIMF_NO_ERROR;
752 int mailimf_fields_write(FILE * f, int * col,
753 struct mailimf_fields * fields)
757 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
758 cur = clist_next(cur)) {
761 r = mailimf_field_write(f, col, clist_content(cur));
762 if (r != MAILIMF_NO_ERROR)
766 return MAILIMF_NO_ERROR;
770 int mailimf_unparsed_fields_write(FILE * f, int * col,
771 struct mailimf_unparsed_fields * fields)
775 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
778 r = mailimf_optional_field_write(f, col, cur->data);
779 if (r != MAILIMF_NO_ERROR)
783 return MAILIMF_NO_ERROR;
787 int mailimf_field_write(FILE * f, int * col,
788 struct mailimf_field * field)
792 switch (field->fld_type) {
793 case MAILIMF_FIELD_RETURN_PATH:
794 r = mailimf_return_write(f, col, field->fld_data.fld_return_path);
796 case MAILIMF_FIELD_RESENT_DATE:
797 r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date);
799 case MAILIMF_FIELD_RESENT_FROM:
800 r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from);
802 case MAILIMF_FIELD_RESENT_SENDER:
803 r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender);
805 case MAILIMF_FIELD_RESENT_TO:
806 r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to);
808 case MAILIMF_FIELD_RESENT_CC:
809 r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc);
811 case MAILIMF_FIELD_RESENT_BCC:
812 r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc);
814 case MAILIMF_FIELD_RESENT_MSG_ID:
815 r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id);
817 case MAILIMF_FIELD_ORIG_DATE:
818 r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date);
820 case MAILIMF_FIELD_FROM:
821 r = mailimf_from_write(f, col, field->fld_data.fld_from);
823 case MAILIMF_FIELD_SENDER:
824 r = mailimf_sender_write(f, col, field->fld_data.fld_sender);
826 case MAILIMF_FIELD_REPLY_TO:
827 r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to);
829 case MAILIMF_FIELD_TO:
830 r = mailimf_to_write(f, col, field->fld_data.fld_to);
832 case MAILIMF_FIELD_CC:
833 r = mailimf_cc_write(f, col, field->fld_data.fld_cc);
835 case MAILIMF_FIELD_BCC:
836 r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc);
838 case MAILIMF_FIELD_MESSAGE_ID:
839 r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id);
841 case MAILIMF_FIELD_IN_REPLY_TO:
842 r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to);
844 case MAILIMF_FIELD_REFERENCES:
845 r = mailimf_references_write(f, col, field->fld_data.fld_references);
847 case MAILIMF_FIELD_SUBJECT:
848 r = mailimf_subject_write(f, col, field->fld_data.fld_subject);
850 case MAILIMF_FIELD_COMMENTS:
851 r = mailimf_comments_write(f, col, field->fld_data.fld_comments);
853 case MAILIMF_FIELD_KEYWORDS:
854 r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords);
856 case MAILIMF_FIELD_OPTIONAL_FIELD:
857 r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field);
860 r = MAILIMF_ERROR_INVAL;
864 if (r != MAILIMF_NO_ERROR)
867 return MAILIMF_NO_ERROR;
871 static int mailimf_orig_date_write(FILE * f, int * col,
872 struct mailimf_orig_date * date)
876 r = mailimf_string_write(f, col, "Date: ", 6);
877 if (r != MAILIMF_NO_ERROR)
880 r = mailimf_date_time_write(f, col, date->dt_date_time);
881 if (r != MAILIMF_NO_ERROR)
884 r = mailimf_string_write(f, col, "\r\n", 2);
885 if (r != MAILIMF_NO_ERROR)
891 return MAILIMF_NO_ERROR;
894 #define MAX_DATE_STR 256
899 static int dayofweek(int year, int month, int day)
901 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
905 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
908 static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
910 static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
911 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
913 static int mailimf_date_time_write(FILE * f, int * col,
914 struct mailimf_date_time * date_time)
917 char date_str[MAX_DATE_STR];
925 tmval.tm_sec = date_time->sec;
926 tmval.tm_min = date_time->min;
927 tmval.tm_hour = date_time->hour;
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_mday = date_time->day;
930 tmval.tm_mon = date_time->month - 1;
931 tmval.tm_year = date_time->year - 1900;
934 timeval = mktime(&tmval);
936 localtime_r(&timeval, &tmval);
939 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
941 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
942 week_of_day_str[wday], date_time->dt_day,
943 month_str[date_time->dt_month - 1],
944 date_time->dt_year, date_time->dt_hour,
945 date_time->dt_min, date_time->dt_sec,
948 r = mailimf_string_write(f, col, date_str, strlen(date_str));
950 if (r != MAILIMF_NO_ERROR)
953 return MAILIMF_NO_ERROR;
956 static int mailimf_from_write(FILE * f, int * col,
957 struct mailimf_from * from)
961 r = mailimf_string_write(f, col, "From: ", 6);
962 if (r != MAILIMF_NO_ERROR)
965 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
966 if (r != MAILIMF_NO_ERROR)
969 r = mailimf_string_write(f, col, "\r\n", 2);
970 if (r != MAILIMF_NO_ERROR)
976 return MAILIMF_NO_ERROR;
979 static int mailimf_sender_write(FILE * f, int * col,
980 struct mailimf_sender * sender)
984 r = mailimf_string_write(f, col, "Sender: ", 8);
985 if (r != MAILIMF_NO_ERROR)
988 r = mailimf_mailbox_write(f, col, sender->snd_mb);
989 if (r != MAILIMF_NO_ERROR)
992 r = mailimf_string_write(f, col, "\r\n", 2);
993 if (r != MAILIMF_NO_ERROR)
999 return MAILIMF_NO_ERROR;
1002 static int mailimf_reply_to_write(FILE * f, int * col,
1003 struct mailimf_reply_to * reply_to)
1007 r = mailimf_string_write(f, col, "Reply-To: ", 10);
1008 if (r != MAILIMF_NO_ERROR)
1011 r = mailimf_address_list_write(f, col, reply_to->rt_addr_list);
1012 if (r != MAILIMF_NO_ERROR)
1015 r = mailimf_string_write(f, col, "\r\n", 2);
1016 if (r != MAILIMF_NO_ERROR)
1022 return MAILIMF_NO_ERROR;
1026 static int mailimf_to_write(FILE * f, int * col,
1027 struct mailimf_to * to)
1031 r = mailimf_string_write(f, col, "To: ", 4);
1032 if (r != MAILIMF_NO_ERROR)
1035 r = mailimf_address_list_write(f, col, to->to_addr_list);
1036 if (r != MAILIMF_NO_ERROR)
1039 r = mailimf_string_write(f, col, "\r\n", 2);
1040 if (r != MAILIMF_NO_ERROR)
1046 return MAILIMF_NO_ERROR;
1050 static int mailimf_cc_write(FILE * f, int * col,
1051 struct mailimf_cc * cc)
1055 r = mailimf_string_write(f, col, "Cc: ", 4);
1056 if (r != MAILIMF_NO_ERROR)
1059 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1060 if (r != MAILIMF_NO_ERROR)
1063 r = mailimf_string_write(f, col, "\r\n", 2);
1064 if (r != MAILIMF_NO_ERROR)
1070 return MAILIMF_NO_ERROR;
1074 static int mailimf_bcc_write(FILE * f, int * col,
1075 struct mailimf_bcc * bcc)
1079 r = mailimf_string_write(f, col, "Bcc: ", 5);
1080 if (r != MAILIMF_NO_ERROR)
1083 if (bcc->bcc_addr_list != NULL) {
1084 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1085 if (r != MAILIMF_NO_ERROR)
1089 r = mailimf_string_write(f, col, "\r\n", 2);
1090 if (r != MAILIMF_NO_ERROR)
1096 return MAILIMF_NO_ERROR;
1100 static int mailimf_message_id_write(FILE * f, int * col,
1101 struct mailimf_message_id * message_id)
1105 r = mailimf_string_write(f, col, "Message-ID: ", 12);
1106 if (r != MAILIMF_NO_ERROR)
1109 r = mailimf_string_write(f, col, "<", 1);
1110 if (r != MAILIMF_NO_ERROR)
1113 r = mailimf_string_write(f, col,
1114 message_id->mid_value,
1115 strlen(message_id->mid_value));
1116 if (r != MAILIMF_NO_ERROR)
1119 r = mailimf_string_write(f, col, ">", 1);
1120 if (r != MAILIMF_NO_ERROR)
1123 r = mailimf_string_write(f, col, "\r\n", 2);
1124 if (r != MAILIMF_NO_ERROR)
1130 return MAILIMF_NO_ERROR;
1134 static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list)
1142 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1146 msgid = clist_content(cur);
1147 len = strlen(msgid);
1150 XXX - if this is the first message ID, don't fold.
1151 This is a workaround for a bug of old versions of INN.
1156 if (* col + len >= MAX_MAIL_COL) {
1157 r = mailimf_string_write(f, col, "\r\n ", 3);
1158 if (r != MAILIMF_NO_ERROR)
1169 r = mailimf_string_write(f, col, " ", 1);
1170 if (r != MAILIMF_NO_ERROR)
1177 r = mailimf_string_write(f, col, "<", 1);
1178 if (r != MAILIMF_NO_ERROR)
1181 r = mailimf_string_write(f, col, msgid, len);
1182 if (r != MAILIMF_NO_ERROR)
1185 r = mailimf_string_write(f, col, ">", 1);
1186 if (r != MAILIMF_NO_ERROR)
1190 return MAILIMF_NO_ERROR;
1194 static int mailimf_in_reply_to_write(FILE * f, int * col,
1195 struct mailimf_in_reply_to * in_reply_to)
1199 r = mailimf_string_write(f, col, "In-Reply-To: ", 13);
1200 if (r != MAILIMF_NO_ERROR)
1203 r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list);
1204 if (r != MAILIMF_NO_ERROR)
1207 r = mailimf_string_write(f, col, "\r\n", 2);
1208 if (r != MAILIMF_NO_ERROR)
1214 return MAILIMF_NO_ERROR;
1218 static int mailimf_references_write(FILE * f, int * col,
1219 struct mailimf_references * references)
1223 r = mailimf_string_write(f, col, "References: ", 12);
1224 if (r != MAILIMF_NO_ERROR)
1227 r = mailimf_msg_id_list_write(f, col, references->mid_list);
1228 if (r != MAILIMF_NO_ERROR)
1231 r = mailimf_string_write(f, col, "\r\n", 2);
1232 if (r != MAILIMF_NO_ERROR)
1238 return MAILIMF_NO_ERROR;
1243 static int mailimf_subject_write(FILE * f, int * col,
1244 struct mailimf_subject * subject)
1248 r = mailimf_string_write(f, col, "Subject: ", 9);
1249 if (r != MAILIMF_NO_ERROR)
1252 r = mailimf_header_string_write(f, col,
1253 subject->sbj_value, strlen(subject->sbj_value));
1254 if (r != MAILIMF_NO_ERROR)
1257 r = mailimf_string_write(f, col, "\r\n", 2);
1258 if (r != MAILIMF_NO_ERROR)
1264 return MAILIMF_NO_ERROR;
1267 int mailimf_address_list_write(FILE * f, int * col,
1268 struct mailimf_address_list * addr_list)
1276 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1277 cur = clist_next(cur)) {
1278 struct mailimf_address * addr;
1280 addr = clist_content(cur);
1283 r = mailimf_string_write(f, col, ", ", 2);
1284 if (r != MAILIMF_NO_ERROR)
1291 r = mailimf_address_write(f, col, addr);
1292 if (r != MAILIMF_NO_ERROR)
1296 return MAILIMF_NO_ERROR;
1300 static int mailimf_address_write(FILE * f, int * col,
1301 struct mailimf_address * addr)
1305 switch(addr->ad_type) {
1306 case MAILIMF_ADDRESS_MAILBOX:
1307 r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox);
1308 if (r != MAILIMF_NO_ERROR)
1313 case MAILIMF_ADDRESS_GROUP:
1314 r = mailimf_group_write(f, col, addr->ad_data.ad_group);
1315 if (r != MAILIMF_NO_ERROR)
1321 return MAILIMF_NO_ERROR;
1325 static int mailimf_group_write(FILE * f, int * col,
1326 struct mailimf_group * group)
1330 r = mailimf_header_string_write(f, col, group->grp_display_name,
1331 strlen(group->grp_display_name));
1332 if (r != MAILIMF_NO_ERROR)
1335 r = mailimf_string_write(f, col, ": ", 2);
1336 if (r != MAILIMF_NO_ERROR)
1339 if (group->grp_mb_list != NULL) {
1340 r = mailimf_mailbox_list_write(f, col, group->grp_mb_list);
1341 if (r != MAILIMF_NO_ERROR)
1345 r = mailimf_string_write(f, col, ";", 1);
1346 if (r != MAILIMF_NO_ERROR)
1349 return MAILIMF_NO_ERROR;
1353 int mailimf_mailbox_list_write(FILE * f, int * col,
1354 struct mailimf_mailbox_list * mb_list)
1362 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1363 cur = clist_next(cur)) {
1364 struct mailimf_mailbox * mb;
1366 mb = clist_content(cur);
1369 r = mailimf_string_write(f, col, ", ", 2);
1370 if (r != MAILIMF_NO_ERROR)
1377 r = mailimf_mailbox_write(f, col, mb);
1378 if (r != MAILIMF_NO_ERROR)
1382 return MAILIMF_NO_ERROR;
1386 int mailimf_quoted_string_write(FILE * f, int * col,
1387 const char * string, size_t len)
1393 for(i = 0 ; i < len ; i ++) {
1394 switch (string[i]) {
1399 return MAILIMF_ERROR_FILE;
1400 r = fputc(string[i], f);
1402 return MAILIMF_ERROR_FILE;
1407 r = fputc(string[i], f);
1409 return MAILIMF_ERROR_FILE;
1416 return MAILIMF_NO_ERROR;
1422 atext = ALPHA / DIGIT / ; Any character except controls,
1423 "!" / "#" / ; SP, and specials.
1424 "$" / "%" / ; Used for atoms
1435 static int is_atext(const char * s)
1439 for(p = s ; * p != 0 ; p ++) {
1440 if (isalpha((unsigned char) * p))
1442 if (isdigit((unsigned char) * p))
1475 static int mailimf_mailbox_write(FILE * f, int * col,
1476 struct mailimf_mailbox * mb)
1484 if (mb->mb_display_name != NULL) {
1485 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1486 r = mailimf_string_write(f, col, "\r\n ", 3);
1487 if (r != MAILIMF_NO_ERROR)
1497 if (mb->mb_display_name) {
1499 if (is_atext(mb->mb_display_name)) {
1500 r = mailimf_header_string_write(f, col, mb->mb_display_name,
1501 strlen(mb->mb_display_name));
1502 if (r != MAILIMF_NO_ERROR)
1506 if (mb->mb_display_name != NULL) {
1507 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1508 r = mailimf_string_write(f, col, "\r\n ", 3);
1509 if (r != MAILIMF_NO_ERROR)
1514 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1515 return MAILIMF_ERROR_INVAL;
1517 r = mailimf_quoted_string_write(f, col, mb->mb_display_name,
1518 strlen(mb->mb_display_name));
1519 if (r != MAILIMF_NO_ERROR)
1526 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1527 r = mailimf_string_write(f, col, "\r\n ", 3);
1528 if (r != MAILIMF_NO_ERROR)
1538 r = mailimf_string_write(f, col, "<", 1);
1540 r = mailimf_string_write(f, col, " <", 2);
1541 if (r != MAILIMF_NO_ERROR)
1544 r = mailimf_string_write(f, col, mb->mb_addr_spec,
1545 strlen(mb->mb_addr_spec));
1546 if (r != MAILIMF_NO_ERROR)
1549 r = mailimf_string_write(f, col, ">", 1);
1550 if (r != MAILIMF_NO_ERROR)
1554 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1555 r = mailimf_string_write(f, col, "\r\n ", 3);
1556 if (r != MAILIMF_NO_ERROR)
1560 r = mailimf_string_write(f, col,
1561 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1562 if (r != MAILIMF_NO_ERROR)
1567 return MAILIMF_NO_ERROR;
1570 static int mailimf_comments_write(FILE * f, int * col,
1571 struct mailimf_comments * comments)
1575 r = mailimf_string_write(f, col, "Comments: ", 10);
1576 if (r != MAILIMF_NO_ERROR)
1579 r = mailimf_header_string_write(f, col,
1580 comments->cm_value, strlen(comments->cm_value));
1581 if (r != MAILIMF_NO_ERROR)
1584 r = mailimf_string_write(f, col, "\r\n", 2);
1585 if (r != MAILIMF_NO_ERROR)
1591 return MAILIMF_NO_ERROR;
1594 static int mailimf_optional_field_write(FILE * f, int * col,
1595 struct mailimf_optional_field * field)
1599 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1600 return MAILIMF_ERROR_INVAL;
1602 r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name));
1603 if (r != MAILIMF_NO_ERROR)
1606 r = mailimf_string_write(f, col, ": ", 2);
1607 if (r != MAILIMF_NO_ERROR)
1610 r = mailimf_header_string_write(f, col, field->fld_value,
1611 strlen(field->fld_value));
1612 if (r != MAILIMF_NO_ERROR)
1616 /* XXX parsing debug */
1617 mailimf_string_write(f, col, " (X)", 4);
1620 r = mailimf_string_write(f, col, "\r\n", 2);
1621 if (r != MAILIMF_NO_ERROR)
1627 return MAILIMF_NO_ERROR;
1630 static int mailimf_keywords_write(FILE * f, int * col,
1631 struct mailimf_keywords * keywords)
1637 r = mailimf_string_write(f, col, "Keywords: ", 10);
1638 if (r != MAILIMF_NO_ERROR)
1643 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1644 cur = clist_next(cur)) {
1648 keyword = clist_content(cur);
1649 len = strlen(keyword);
1652 r = mailimf_string_write(f, col, ", ", 2);
1653 if (r != MAILIMF_NO_ERROR)
1663 if (* col + len >= MAX_MAIL_COL) {
1664 r = mailimf_string_write(f, col, "\r\n ", 3);
1665 if (r != MAILIMF_NO_ERROR)
1674 r = mailimf_header_string_write(f, col, keyword, len);
1675 if (r != MAILIMF_NO_ERROR)
1679 r = mailimf_string_write(f, col, "\r\n", 2);
1680 if (r != MAILIMF_NO_ERROR)
1686 return MAILIMF_NO_ERROR;
1690 static int mailimf_delivering_info_write(FILE * f, int * col,
1691 struct mailimf_delivering_info * info)
1696 for(cur = clist_begin(info->received_fields) ;
1697 cur != NULL ; cur = cur->next) {
1698 struct mailimf_trace_resent_fields * field;
1702 r = mailimf_trace_resent_fields_write(f, col, field);
1703 if (r != MAILIMF_NO_ERROR)
1707 return MAILIMF_NO_ERROR;
1712 mailimf_trace_resent_fields_write(FILE * f, int * col,
1713 struct mailimf_trace_resent_fields * field)
1717 if (field->return_path != NULL) {
1718 r = mailimf_return_write(f, col, field->return_path);
1719 if (r != MAILIMF_NO_ERROR)
1723 if (field->resent_fields != NULL) {
1724 r = mailimf_resent_fields_write(f, col, field->resent_fields);
1725 if (r != MAILIMF_NO_ERROR)
1729 return MAILIMF_NO_ERROR;
1733 static int mailimf_return_write(FILE * f, int * col,
1734 struct mailimf_return * return_path)
1738 r = mailimf_string_write(f, col, "Return-Path: ", 13);
1739 if (r != MAILIMF_NO_ERROR)
1742 r = mailimf_path_write(f, col, return_path->ret_path);
1743 if (r != MAILIMF_NO_ERROR)
1746 r = mailimf_string_write(f, col, "\r\n", 2);
1747 if (r != MAILIMF_NO_ERROR)
1753 return MAILIMF_NO_ERROR;
1756 static int mailimf_path_write(FILE * f, int * col,
1757 struct mailimf_path * path)
1761 r = mailimf_string_write(f, col, "<", 1);
1762 if (r != MAILIMF_NO_ERROR)
1765 r = mailimf_string_write(f, col, path->pt_addr_spec,
1766 strlen(path->pt_addr_spec));
1767 if (r != MAILIMF_NO_ERROR)
1770 r = mailimf_string_write(f, col, ">", 1);
1771 if (r != MAILIMF_NO_ERROR)
1774 return MAILIMF_NO_ERROR;
1778 static int mailimf_resent_fields_write(FILE * f, int * col,
1779 struct mailimf_resent_fields_list *
1785 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1786 struct mailimf_resent_field * field;
1790 r = mailimf_resent_field_write(f, col, field);
1791 if (r != MAILIMF_NO_ERROR)
1795 return MAILIMF_NO_ERROR;
1800 static int mailimf_resent_field_write(FILE * f, int * col,
1801 struct mailimf_resent_field *
1806 switch (resent_field->type) {
1807 case MAILIMF_RESENT_FIELD_DATE:
1808 r = mailimf_resent_date_write(f, col, resent_field->resent_date);
1811 case MAILIMF_RESENT_FIELD_FROM:
1812 r = mailimf_resent_from_write(f, col, resent_field->resent_from);
1815 case MAILIMF_RESENT_FIELD_SENDER:
1816 r = mailimf_resent_sender_write(f, col, resent_field->resent_sender);
1819 case MAILIMF_RESENT_FIELD_TO:
1820 r = mailimf_resent_to_write(f, col, resent_field->resent_to);
1823 case MAILIMF_RESENT_FIELD_CC:
1824 r = mailimf_resent_cc_write(f, col, resent_field->resent_cc);
1827 case MAILIMF_RESENT_FIELD_BCC:
1828 r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc);
1831 case MAILIMF_RESENT_FIELD_MSG_ID:
1832 r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id);
1835 r = MAILIMF_ERROR_INVAL;
1840 if (r != MAILIMF_NO_ERROR)
1843 return MAILIMF_NO_ERROR;
1847 static int mailimf_resent_date_write(FILE * f, int * col,
1848 struct mailimf_orig_date * date)
1852 r = mailimf_string_write(f, col, "Resent-Date: ", 13);
1853 if (r != MAILIMF_NO_ERROR)
1856 r = mailimf_date_time_write(f, col, date->dt_date_time);
1857 if (r != MAILIMF_NO_ERROR)
1860 r = mailimf_string_write(f, col, "\r\n", 2);
1861 if (r != MAILIMF_NO_ERROR)
1867 return MAILIMF_NO_ERROR;
1870 static int mailimf_resent_from_write(FILE * f, int * col,
1871 struct mailimf_from * from)
1875 r = mailimf_string_write(f, col, "Resent-From: ", 13);
1876 if (r != MAILIMF_NO_ERROR)
1879 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
1880 if (r != MAILIMF_NO_ERROR)
1883 r = mailimf_string_write(f, col, "\r\n", 2);
1884 if (r != MAILIMF_NO_ERROR)
1890 return MAILIMF_NO_ERROR;
1893 static int mailimf_resent_sender_write(FILE * f, int * col,
1894 struct mailimf_sender * sender)
1898 r = mailimf_string_write(f, col, "Resent-Sender: ", 15);
1899 if (r != MAILIMF_NO_ERROR)
1902 r = mailimf_mailbox_write(f, col, sender->snd_mb);
1903 if (r != MAILIMF_NO_ERROR)
1906 r = mailimf_string_write(f, col, "\r\n", 2);
1907 if (r != MAILIMF_NO_ERROR)
1913 return MAILIMF_NO_ERROR;
1916 static int mailimf_resent_to_write(FILE * f, int * col,
1917 struct mailimf_to * to)
1921 r = mailimf_string_write(f, col, "Resent-To: ", 11);
1922 if (r != MAILIMF_NO_ERROR)
1925 r = mailimf_address_list_write(f, col, to->to_addr_list);
1926 if (r != MAILIMF_NO_ERROR)
1929 r = mailimf_string_write(f, col, "\r\n", 2);
1930 if (r != MAILIMF_NO_ERROR)
1936 return MAILIMF_NO_ERROR;
1940 static int mailimf_resent_cc_write(FILE * f, int * col,
1941 struct mailimf_cc * cc)
1945 r = mailimf_string_write(f, col, "Resent-Cc: ", 11);
1946 if (r != MAILIMF_NO_ERROR)
1949 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1950 if (r != MAILIMF_NO_ERROR)
1953 r = mailimf_string_write(f, col, "\r\n", 2);
1954 if (r != MAILIMF_NO_ERROR)
1960 return MAILIMF_NO_ERROR;
1964 static int mailimf_resent_bcc_write(FILE * f, int * col,
1965 struct mailimf_bcc * bcc)
1969 r = mailimf_string_write(f, col, "Resent-Bcc: ", 12);
1970 if (r != MAILIMF_NO_ERROR)
1973 if (bcc->bcc_addr_list != NULL) {
1974 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1975 if (r != MAILIMF_NO_ERROR)
1979 r = mailimf_string_write(f, col, "\r\n", 2);
1980 if (r != MAILIMF_NO_ERROR)
1986 return MAILIMF_NO_ERROR;
1991 mailimf_resent_msg_id_write(FILE * f, int * col,
1992 struct mailimf_message_id * message_id)
1996 r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19);
1997 if (r != MAILIMF_NO_ERROR)
2000 r = mailimf_string_write(f, col, "<", 1);
2001 if (r != MAILIMF_NO_ERROR)
2004 r = mailimf_string_write(f, col,
2005 message_id->mid_value, strlen(message_id->mid_value));
2006 if (r != MAILIMF_NO_ERROR)
2009 r = mailimf_string_write(f, col, ">", 1);
2010 if (r != MAILIMF_NO_ERROR)
2013 r = mailimf_string_write(f, col, "\r\n", 2);
2014 if (r != MAILIMF_NO_ERROR)
2020 return MAILIMF_NO_ERROR;