14 #define USERAGENT "git://repo.or.cz/mailx.git"
16 static int isaddr(int c
)
18 return isalpha(c
) || isdigit(c
) || strchr("_.-@", c
);
21 static char *cut_addr(char *dst
, char *src
)
23 while (*src
&& !isaddr(*src
))
31 static int parse_addr(char **recips
, int size
, char *s
, int len
)
35 while (n
< size
&& s
< d
&& *(s
= cut_addr(recips
[n
], s
)))
36 if (strchr(recips
[n
], '@'))
41 static int mail_recips(char **recips
, int size
, char *s
)
43 struct mail mail
= {{0}};
47 if ((to
= mail_hdr(&mail
, "To:")))
48 n
+= parse_addr(recips
+ n
, size
- n
, to
+ 3, hdr_len(to
) - 3);
49 if ((cc
= mail_hdr(&mail
, "CC:")))
50 n
+= parse_addr(recips
+ n
, size
- n
, cc
+ 3, hdr_len(cc
) - 3);
54 static char *put_from_(char *s
)
58 s
= put_str(s
, "From ");
59 s
= put_str(s
, getlogin());
60 s
+= strftime(s
, MAXLINE
, " %a %b %d %H:%M:%S %Y\n", localtime(&t
));
64 static char *put_date(char *s
)
70 s
= put_str(s
, "Date: ");
71 s
+= strftime(s
, MAXLINE
, "%a, %d %b %Y %H:%M:%S ", localtime(&t
));
73 *s
++ = timezone
< 0 ? '-' : '+';
74 s
= put_intz(s
, tz
/ 3600, 2);
75 s
= put_intz(s
, (tz
% 3600) / 60, 2);
80 static char *put_id(char *s
)
84 s
= put_str(s
, "Message-ID: <");
85 s
+= strftime(s
, MAXLINE
, "%Y%d%m%H%M%S", localtime(&t
));
86 s
= put_str(s
, "@" HOSTNAME
">\n");
90 static char *put_from(char *s
)
92 return FROM
? put_str(s
, "From: " FROM
"\n") : s
;
95 static char *put_to(char *s
, char **to
, int n
)
98 s
= put_str(s
, "To: ");
99 s
= put_str(s
, to
[0]);
100 for (i
= 1; i
< n
; i
++) {
101 s
= put_str(s
, ",\n\t");
102 s
= put_str(s
, to
[i
]);
104 s
= put_str(s
, "\n");
108 static char *put_subj(char *s
, char *subj
)
110 s
= put_str(s
, "Subject: ");
111 s
= put_str(s
, subj
);
112 s
= put_str(s
, "\n");
116 static char *put_agent(char *s
)
118 return put_str(s
, "User-Agent: " USERAGENT
"\n");
121 void draft_init(struct draft
*draft
, char **to
, int nto
, char *subj
)
123 char *s
= draft
->mail
;
128 s
= put_to(s
, to
, nto
);
130 s
= put_subj(s
, subj
);
133 draft
->len
= s
- draft
->mail
;
136 static char *hdr_val(char *hdr
)
138 hdr
= strchr(hdr
, ':') + 1;
139 while (isspace(*hdr
))
144 static char *put_replysubj(char *s
, char *subj
)
146 subj
= hdr_val(subj
);
147 s
= put_str(s
, "Subject: ");
148 if (tolower(subj
[0]) != 'r' || tolower(subj
[1]) != 'e')
149 s
= put_str(s
, "Re: ");
150 s
= put_mem(s
, subj
, hdr_len(subj
));
154 static char *put_replyto(char *s
, char *id
, char *ref
)
156 s
= put_str(s
, "In-Reply-To: ");
158 s
= put_mem(s
, id
, hdr_len(id
));
159 s
= put_str(s
, "References: ");
162 s
= put_mem(s
, ref
, hdr_len(ref
));
163 s
= put_str(s
, "\t");
165 s
= put_mem(s
, id
, hdr_len(id
));
169 static char *put_reply(char *s
, char *from
, char *to
, char *cc
)
172 from
= hdr_val(from
);
173 s
= put_str(s
, "To: ");
174 s
= put_mem(s
, from
, hdr_len(from
));
177 s
= put_str(s
, "Cc: ");
180 s
= put_mem(s
, to
, hdr_len(to
));
185 s
= put_str(s
, "\t");
186 s
= put_mem(s
, cc
, hdr_len(cc
));
192 void draft_reply(struct draft
*draft
, struct mail
*mail
)
194 char *s
= draft
->mail
;
195 char *id_hdr
= mail_hdr(mail
, "Message-ID:");
196 char *ref_hdr
= mail_hdr(mail
, "References:");
197 char *from_hdr
= mail_hdr(mail
, "From:");
198 char *subj_hdr
= mail_hdr(mail
, "Subject:");
199 char *to_hdr
= mail_hdr(mail
, "To:");
200 char *cc_hdr
= mail_hdr(mail
, "CC:");
205 s
= put_reply(s
, from_hdr
, to_hdr
, cc_hdr
);
207 s
= put_replysubj(s
, subj_hdr
);
210 s
= put_replyto(s
, id_hdr
, ref_hdr
);
212 draft
->len
= s
- draft
->mail
;
215 void draft_edit(struct draft
*draft
)
217 char *edit_argv
[] = {EDITOR
, DRAFT
, NULL
};
219 if ((fd
= open(DRAFT
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
)) == -1)
221 xwrite(fd
, draft
->mail
, draft
->len
);
223 exec_file(EDITOR
, edit_argv
);
224 if ((fd
= open(DRAFT
, O_RDONLY
)) == -1)
226 draft
->len
= xread(fd
, draft
->mail
, sizeof(draft
->mail
) - 1);
228 draft
->mail
[draft
->len
] = '\0';
232 void draft_send(struct draft
*draft
)
234 char recips
[MAXRECP
][MAXLINE
];
235 char *send_argv
[MAXRECP
+ 3] = {SENDMAIL
, "-i"};
236 char *beg
= strchr(draft
->mail
, '\n') + 1;
237 char *end
= draft
->mail
+ draft
->len
;
239 for (i
= 0; i
< MAXRECP
; i
++)
240 send_argv
[i
+ 2] = recips
[i
];
241 send_argv
[2 + mail_recips(send_argv
+ 2, MAXRECP
, draft
->mail
)] = NULL
;
242 exec_pipe(SENDMAIL
, send_argv
, beg
, end
- beg
);
245 static void write_nofrom(int fd
, char *s
, int len
)
251 if (!strncmp("\nFrom ", s
, 6)) {
252 write(fd
, beg
, s
- beg
+ 1);
256 r
= strchr(s
+ 1, '\n');
259 write(fd
, beg
, s
- beg
);
262 void draft_save(struct draft
*draft
, char *path
)
264 int fd
= open(path
, O_WRONLY
| O_APPEND
| O_CREAT
, S_IRUSR
| S_IWUSR
);
267 write_nofrom(fd
, draft
->mail
, draft
->len
);