14 static int isaddr(int c
)
16 return isalpha(c
) || isdigit(c
) || strchr("_.-@", c
);
19 static char *cut_addr(char *dst
, char *src
)
21 while (*src
&& !isaddr(*src
))
29 static int parse_addr(char **recips
, int size
, char *s
, int len
)
33 while (n
< size
&& s
< d
&& *(s
= cut_addr(recips
[n
], s
)))
34 if (strchr(recips
[n
], '@'))
39 static int mail_recips(char **recips
, int size
, char *s
)
41 struct mail mail
= {{0}};
45 if ((to
= mail_hdr(&mail
, "To:")))
46 n
+= parse_addr(recips
+ n
, size
- n
, to
+ 3, hdr_len(to
) - 3);
47 if ((cc
= mail_hdr(&mail
, "CC:")))
48 n
+= parse_addr(recips
+ n
, size
- n
, cc
+ 3, hdr_len(cc
) - 3);
52 static char *put_from_(char *s
)
56 s
= put_str(s
, "From ");
57 s
= put_str(s
, getlogin());
58 s
+= strftime(s
, MAXLINE
, " %a %b %d %H:%M:%S %Y\n", localtime(&t
));
62 static char *put_date(char *s
)
68 s
= put_str(s
, "Date: ");
69 s
+= strftime(s
, MAXLINE
, "%a, %d %b %Y %H:%M:%S ", localtime(&t
));
71 *s
++ = timezone
< 0 ? '-' : '+';
72 s
= put_intz(s
, tz
/ 3600, 2);
73 s
= put_intz(s
, (tz
% 3600) / 60, 2);
78 static char *put_id(char *s
)
82 s
= put_str(s
, "Message-ID: <");
83 s
+= strftime(s
, MAXLINE
, "%Y%d%m%H%M%S", localtime(&t
));
84 s
= put_str(s
, "@" HOSTNAME
">\n");
88 static char *put_from(char *s
)
90 return FROM
? put_str(s
, "From: " FROM
"\n") : s
;
93 static char *put_to(char *s
, char **to
, int n
)
96 s
= put_str(s
, "To: ");
97 s
= put_str(s
, to
[0]);
98 for (i
= 1; i
< n
; i
++) {
99 s
= put_str(s
, ",\n\t");
100 s
= put_str(s
, to
[i
]);
102 s
= put_str(s
, "\n");
106 static char *put_subj(char *s
, char *subj
)
108 s
= put_str(s
, "Subject: ");
109 s
= put_str(s
, subj
);
110 s
= put_str(s
, "\n");
114 void draft_init(struct draft
*draft
, char **to
, int nto
, char *subj
)
116 char *s
= draft
->mail
;
122 s
= put_to(s
, to
, nto
);
124 s
= put_subj(s
, subj
);
125 draft
->len
= s
- draft
->mail
;
128 static char *hdr_val(char *hdr
)
130 hdr
= strchr(hdr
, ':') + 1;
131 while (isspace(*hdr
))
136 static char *put_replysubj(char *s
, char *subj
)
138 subj
= hdr_val(subj
);
139 s
= put_str(s
, "Subject: ");
140 if (tolower(subj
[0]) != 'r' || tolower(subj
[1]) != 'e')
141 s
= put_str(s
, "Re: ");
142 s
= put_mem(s
, subj
, hdr_len(subj
));
146 static char *put_replyto(char *s
, char *id
, char *ref
)
148 s
= put_str(s
, "In-Reply-To: ");
150 s
= put_mem(s
, id
, hdr_len(id
));
151 s
= put_str(s
, "References: ");
152 s
= put_mem(s
, id
, hdr_len(id
));
155 s
= put_str(s
, "\t");
156 s
= put_mem(s
, ref
, hdr_len(ref
));
161 static char *put_reply(char *s
, char *from
, char *to
, char *cc
)
164 from
= hdr_val(from
);
165 s
= put_str(s
, "To: ");
166 s
= put_mem(s
, from
, hdr_len(from
));
169 s
= put_str(s
, "Cc: ");
172 s
= put_mem(s
, to
, hdr_len(to
));
177 s
= put_str(s
, "\t");
178 s
= put_mem(s
, cc
, hdr_len(cc
));
184 void draft_reply(struct draft
*draft
, struct mail
*mail
)
186 char *s
= draft
->mail
;
187 char *id_hdr
= mail_hdr(mail
, "Message-ID:");
188 char *ref_hdr
= mail_hdr(mail
, "References:");
189 char *from_hdr
= mail_hdr(mail
, "From:");
190 char *subj_hdr
= mail_hdr(mail
, "Subject:");
191 char *to_hdr
= mail_hdr(mail
, "To:");
192 char *cc_hdr
= mail_hdr(mail
, "CC:");
199 s
= put_replysubj(s
, subj_hdr
);
201 s
= put_replyto(s
, id_hdr
, ref_hdr
);
202 s
= put_reply(s
, from_hdr
, to_hdr
, cc_hdr
);
203 draft
->len
= s
- draft
->mail
;
206 void draft_edit(struct draft
*draft
)
208 char *edit_argv
[] = {EDITOR
, DRAFT
, NULL
};
210 if ((fd
= open(DRAFT
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
)) == -1)
212 xwrite(fd
, draft
->mail
, draft
->len
);
214 exec_file(EDITOR
, edit_argv
);
215 if ((fd
= open(DRAFT
, O_RDONLY
)) == -1)
217 draft
->len
= xread(fd
, draft
->mail
, sizeof(draft
->mail
) - 1);
219 draft
->mail
[draft
->len
] = '\0';
223 void draft_send(struct draft
*draft
)
225 char recips
[MAXRECP
][MAXLINE
];
226 char *send_argv
[MAXRECP
+ 3] = {SENDMAIL
, "-i"};
227 char *beg
= strchr(draft
->mail
, '\n') + 1;
228 char *end
= draft
->mail
+ draft
->len
;
230 for (i
= 0; i
< MAXRECP
; i
++)
231 send_argv
[i
+ 2] = recips
[i
];
232 send_argv
[2 + mail_recips(send_argv
+ 2, MAXRECP
, draft
->mail
)] = NULL
;
233 exec_pipe(SENDMAIL
, send_argv
, beg
, end
- beg
);
236 void draft_save(struct draft
*draft
, char *path
)
238 struct mail mail
= {{0}};
239 int fd
= open(path
, O_WRONLY
| O_APPEND
| O_CREAT
, S_IRUSR
| S_IWUSR
);
242 mail_read(&mail
, draft
->mail
);
243 mail_write(&mail
, fd
);