Mercurial > masqmail
comparison src/accept.c @ 388:aa40710f09fe
Refactoring and code layouting.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sat, 18 Feb 2012 13:37:40 +0100 |
parents | 5781ba87df95 |
children | 9b93c0a3bd8c |
comparison
equal
deleted
inserted
replaced
387:a408411ff8df | 388:aa40710f09fe |
---|---|
30 }; | 30 }; |
31 | 31 |
32 static gchar* | 32 static gchar* |
33 string_base62(gchar *res, guint value, gchar len) | 33 string_base62(gchar *res, guint value, gchar len) |
34 { | 34 { |
35 static gchar base62_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | 35 static gchar base62_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
36 "abcdefghijklmnopqrstuvwxyz"; | |
36 gchar *p = res + len; | 37 gchar *p = res + len; |
37 *p = '\0'; | 38 *p = '\0'; |
38 while (p > res) { | 39 while (p > res) { |
39 *(--p) = base62_chars[value % 62]; | 40 *(--p) = base62_chars[value % 62]; |
40 value /= 62; | 41 value /= 62; |
47 ** A message from local is indicated by msg->recieved_host == NULL | 48 ** A message from local is indicated by msg->recieved_host == NULL |
48 ** | 49 ** |
49 ** The -t option: With the ACC_RCPT_FROM_HEAD flag the addrs found found | 50 ** The -t option: With the ACC_RCPT_FROM_HEAD flag the addrs found found |
50 ** in To/Cc/Bcc headers are added to the recipient list. | 51 ** in To/Cc/Bcc headers are added to the recipient list. |
51 */ | 52 */ |
52 | |
53 accept_error | 53 accept_error |
54 accept_message_stream(FILE *in, message *msg, guint flags) | 54 accept_message_stream(FILE *in, message *msg, guint flags) |
55 { | 55 { |
56 gchar *line, *line1; | 56 gchar *line, *line1; |
57 int line_size = MAX_DATALINE; | 57 int line_size = MAX_DATALINE; |
58 gboolean in_headers = TRUE; | 58 gboolean in_headers = TRUE; |
59 header *hdr = NULL; | 59 header *hdr = NULL; |
60 gint line_cnt = 0, data_size = 0; | 60 gint line_cnt = 0, data_size = 0; |
61 | 61 |
62 line = g_malloc(line_size); | 62 line = g_malloc(line_size); |
63 line[0] = '\0'; | 63 *line = '\0'; |
64 | 64 |
65 while (TRUE) { | 65 while (1) { |
66 int len = read_sockline1(in, &line, &line_size, 5 * 60, READSOCKL_CVT_CRLF); | 66 int len = read_sockline1(in, &line, &line_size, 5 * 60, |
67 | 67 READSOCKL_CVT_CRLF); |
68 line1 = line; | 68 line1 = line; |
69 | 69 |
70 if ((line[0] == '.') && (!(flags & ACC_DOT_IGNORE))) { | 70 if ((*line == '.') && (!(flags & ACC_DOT_IGNORE))) { |
71 if (line[1] == '\n') { | 71 if (line[1] == '\n') { |
72 g_free(line); | 72 g_free(line); |
73 break; | 73 break; |
74 } | 74 } |
75 line1++; | 75 line1++; |
76 } | 76 } |
77 | 77 |
78 if ((len == -1) && (flags & (ACC_DOT_IGNORE | ACC_NODOT_RELAX))) { | 78 if (len==-1 && (flags & (ACC_DOT_IGNORE | ACC_NODOT_RELAX))) { |
79 /* we got an EOF, and the last line was not terminated by a CR */ | 79 /* at EOF but last line was not terminated by CR */ |
80 /* some MUAs allow unterminated lines */ | |
80 gint len1 = strlen(line1); | 81 gint len1 = strlen(line1); |
81 if (len1 > 0) { /* == 0 is 'normal' (EOF after a CR) */ | 82 if (len1 > 0 && line1[len1-1] != '\n') { |
82 if (line1[len1 - 1] != '\n') { /* some mail clients allow unterminated lines */ | 83 line1[len1] = '\n'; |
83 line1[len1] = '\n'; | 84 line1[len1+1] = '\0'; |
84 line1[len1 + 1] = '\0'; | 85 msg->data_list = g_list_prepend(msg->data_list, |
85 msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1)); | 86 g_strdup(line1)); |
86 data_size += strlen(line1); | 87 data_size += strlen(line1); |
87 line_cnt++; | 88 line_cnt++; |
88 } | |
89 } | 89 } |
90 break; | 90 break; |
91 | 91 |
92 } else if (len == -1) { | 92 } else if (len == -1) { |
93 g_free(line); | 93 g_free(line); |
109 return AERR_UNKNOWN; | 109 return AERR_UNKNOWN; |
110 | 110 |
111 } | 111 } |
112 | 112 |
113 if (in_headers) { | 113 if (in_headers) { |
114 | |
115 /* some pop servers send the 'From ' line, skip it: */ | 114 /* some pop servers send the 'From ' line, skip it: */ |
116 if (!msg->hdr_list && strncmp(line1, "From ", 5) == 0) { | 115 if (!msg->hdr_list && strncmp(line1, "From ", 5)==0) { |
117 continue; | 116 continue; |
118 } | 117 } |
119 | 118 |
120 if (line1[0] == ' ' || line1[0] == '\t') { | 119 if (*line1 == ' ' || *line1 == '\t') { |
121 /* continuation of 'folded' header: */ | 120 /* continuation of 'folded' header: */ |
122 if (hdr) { | 121 if (hdr) { |
123 char *cp; | 122 char *cp; |
124 cp = g_strconcat(hdr->header, line1, NULL); | 123 cp = g_strconcat(hdr->header, line1, |
125 hdr->value = cp + (hdr->value - hdr->header); | 124 NULL); |
125 hdr->value = cp + (hdr->value - | |
126 hdr->header); | |
126 free(hdr->header); | 127 free(hdr->header); |
127 hdr->header = cp; | 128 hdr->header = cp; |
128 } | 129 } |
129 | 130 } else if (*line1 == '\n') { |
130 } else if (line1[0] == '\n') { | |
131 /* an empty line marks end of headers */ | 131 /* an empty line marks end of headers */ |
132 in_headers = FALSE; | 132 in_headers = FALSE; |
133 | |
134 } else if ((hdr = get_header(line1))) { | |
135 /* another header */ | |
136 msg->hdr_list = g_list_append(msg->hdr_list, hdr); | |
133 } else { | 137 } else { |
134 /* in all other cases we expect another header */ | 138 /* |
135 if ((hdr = get_header(line1))) { | 139 ** Should be another header but none was |
136 msg->hdr_list = g_list_append(msg->hdr_list, hdr); | 140 ** recognized, so this seems to be the first |
137 } else { | 141 ** data line of a broken mailer which does |
138 /* | 142 ** not add an empty line after the headers. |
139 ** if get_header() returns NULL, | 143 */ |
140 ** no header was recognized, | 144 in_headers = FALSE; |
141 ** so this seems to be the first | 145 msg->data_list = g_list_prepend(msg->data_list, |
142 ** data line of a broken mailer | 146 g_strdup(line1)); |
143 ** which does not send an empty | |
144 ** line after the headers | |
145 */ | |
146 in_headers = FALSE; | |
147 msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1)); | |
148 } | |
149 } | 147 } |
150 } else { | 148 } else { |
151 /* message body */ | 149 /* message body */ |
152 msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1)); | 150 msg->data_list = g_list_prepend(msg->data_list, |
151 g_strdup(line1)); | |
153 data_size += strlen(line1); | 152 data_size += strlen(line1); |
154 line_cnt++; | 153 line_cnt++; |
155 } | 154 } |
156 | 155 |
157 if (conf.max_msg_size && (data_size > conf.max_msg_size)) { | 156 if (conf.max_msg_size && (data_size > conf.max_msg_size)) { |
158 DEBUG(4) debugf("accept_message_stream(): " | 157 DEBUG(4) debugf("accept_message_stream(): " |
159 "received %d bytes (conf.max_msg_size=%d)\n", | 158 "received %d bytes (conf.max_msg_size=%d)\n", |
160 data_size, conf.max_msg_size); | 159 data_size, conf.max_msg_size); |
161 return AERR_SIZE; | 160 return AERR_SIZE; |
162 } | 161 } |
163 | 162 } |
164 } | 163 DEBUG(4) debugf("received %d lines of data (%d bytes)\n", |
165 | 164 line_cnt, data_size); |
166 DEBUG(4) debugf("received %d lines of data (%d bytes)\n", line_cnt, data_size); | |
167 | 165 |
168 if (!msg->data_list) { | 166 if (!msg->data_list) { |
169 /* make sure data list is not NULL: */ | 167 /* make sure data list is not NULL */ |
170 msg->data_list = g_list_append(NULL, g_strdup("")); | 168 msg->data_list = g_list_append(NULL, g_strdup("")); |
171 } | 169 } |
172 msg->data_list = g_list_reverse(msg->data_list); | 170 msg->data_list = g_list_reverse(msg->data_list); |
173 | 171 |
174 /* we get here after we succesfully received the mail data */ | 172 /* we have succesfully received the mail data */ |
175 | 173 |
176 msg->data_size = data_size; | 174 msg->data_size = data_size; |
177 msg->received_time = time(NULL); | 175 msg->received_time = time(NULL); |
178 | 176 |
179 return AERR_OK; | 177 return AERR_OK; |
180 } | 178 } |
181 | 179 |
180 static void | |
181 ensure_return_path(message *msg) | |
182 { | |
183 GList *hdr_list; | |
184 header *hdr; | |
185 gchar *addr; | |
186 | |
187 if (msg->return_path) { | |
188 return; | |
189 } | |
190 | |
191 DEBUG(3) debugf("return_path == NULL\n"); | |
192 | |
193 hdr_list = find_header(msg->hdr_list, HEAD_SENDER, NULL); | |
194 if (!hdr_list) { | |
195 hdr_list = find_header(msg->hdr_list, HEAD_FROM, NULL); | |
196 } | |
197 if (hdr_list) { | |
198 hdr = (header *) (g_list_first(hdr_list)->data); | |
199 | |
200 DEBUG(5) debugf("hdr->value = '%s'\n", hdr->value); | |
201 | |
202 addr = g_strdup(hdr->value); | |
203 g_strchomp(addr); | |
204 msg->return_path = create_address_qualified(addr, | |
205 FALSE, msg->received_host); | |
206 if (msg->return_path) { | |
207 DEBUG(3) debugf("setting return_path to %s\n", | |
208 addr_string(msg->return_path)); | |
209 msg->hdr_list = g_list_append(msg->hdr_list, | |
210 create_header(HEAD_UNKNOWN, | |
211 "X-Warning: return path set from %s " | |
212 "address\n", | |
213 (hdr->id == HEAD_SENDER) ? | |
214 "Sender:" : "From:")); | |
215 } | |
216 g_free(addr); | |
217 } | |
218 if (!msg->return_path) { | |
219 /* no Sender: or From: or create_address_qualified failed */ | |
220 msg->return_path = create_address_qualified("postmaster", | |
221 TRUE, conf.host_name); | |
222 DEBUG(3) debugf("setting return_path to %s\n", | |
223 addr_string(msg->return_path)); | |
224 msg->hdr_list = g_list_append(msg->hdr_list, | |
225 create_header(HEAD_UNKNOWN, | |
226 "X-Warning: real return path is unknown\n")); | |
227 } | |
228 } | |
229 | |
230 static accept_error | |
231 scan_headers(message *msg, guint flags) | |
232 { | |
233 gboolean has_id = FALSE; | |
234 gboolean has_date = FALSE; | |
235 gboolean has_sender = FALSE; | |
236 gboolean has_from = FALSE; | |
237 gboolean has_to_or_cc = FALSE; | |
238 GList *hdr_node, *hdr_node_next; | |
239 header *hdr; | |
240 | |
241 for (hdr_node = g_list_first(msg->hdr_list); hdr_node; | |
242 hdr_node = hdr_node_next) { | |
243 hdr_node_next = g_list_next(hdr_node); | |
244 hdr = ((header *) (hdr_node->data)); | |
245 DEBUG(5) debugf("scanning headers: %s", hdr->header); | |
246 switch (hdr->id) { | |
247 case HEAD_MESSAGE_ID: | |
248 has_id = TRUE; | |
249 break; | |
250 case HEAD_DATE: | |
251 has_date = TRUE; | |
252 break; | |
253 case HEAD_FROM: | |
254 has_from = TRUE; | |
255 break; | |
256 case HEAD_SENDER: | |
257 has_sender = TRUE; | |
258 break; | |
259 case HEAD_TO: | |
260 case HEAD_CC: | |
261 has_to_or_cc = TRUE; | |
262 /* fall through */ | |
263 case HEAD_BCC: | |
264 if (flags & ACC_RCPT_FROM_HEAD) { | |
265 /* -t option (see comment above) */ | |
266 DEBUG(5) debugf("hdr->value = %s\n", | |
267 hdr->value); | |
268 if (hdr->value) { | |
269 msg->rcpt_list = addr_list_append_rfc822(msg->rcpt_list, hdr->value, conf.host_name); | |
270 } | |
271 } | |
272 if (hdr->id == HEAD_BCC) { | |
273 DEBUG(3) debugf("removing 'Bcc' header\n"); | |
274 msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node); | |
275 g_list_free_1(hdr_node); | |
276 destroy_header(hdr); | |
277 } | |
278 break; | |
279 case HEAD_ENVELOPE_TO: | |
280 if (flags & ACC_SAVE_ENVELOPE_TO) { | |
281 DEBUG(3) debugf("creating 'X-Orig-Envelope-To' header\n"); | |
282 msg->hdr_list = g_list_prepend(msg->hdr_list, | |
283 create_header(HEAD_UNKNOWN, | |
284 "X-Orig-Envelope-To: %s", | |
285 hdr->value)); | |
286 } | |
287 DEBUG(3) debugf("removing 'Envelope-To' header\n"); | |
288 msg->hdr_list = g_list_remove_link(msg->hdr_list, | |
289 hdr_node); | |
290 g_list_free_1(hdr_node); | |
291 destroy_header(hdr); | |
292 break; | |
293 case HEAD_RETURN_PATH: | |
294 if (flags & ACC_MAIL_FROM_HEAD) { | |
295 /* usually POP3 accept */ | |
296 msg->return_path = create_address_qualified(hdr->value, TRUE, msg->received_host); | |
297 DEBUG(3) debugf("setting return_path to %s\n", | |
298 addr_string(msg->return_path)); | |
299 } | |
300 DEBUG(3) debugf("removing 'Return-Path' header\n"); | |
301 msg->hdr_list = g_list_remove_link(msg->hdr_list, | |
302 hdr_node); | |
303 g_list_free_1(hdr_node); | |
304 destroy_header(hdr); | |
305 break; | |
306 default: | |
307 break; /* make compiler happy */ | |
308 } | |
309 } | |
310 | |
311 /* | |
312 ** TODO: do we still need this as we don't fetch | |
313 ** mail anymore? | |
314 ** This can happen for pop3 accept only and if no | |
315 ** Return-Path: header was given | |
316 */ | |
317 ensure_return_path(msg); | |
318 | |
319 /* here we should have our recipients, fail if not: */ | |
320 if (!msg->rcpt_list) { | |
321 logwrite(LOG_WARNING, "no recipients found in message\n"); | |
322 return AERR_NORCPT; | |
323 } | |
324 | |
325 if (!has_sender && !has_from) { | |
326 DEBUG(3) debugf("adding 'From:' header\n"); | |
327 if (msg->full_sender_name) { | |
328 msg->hdr_list = g_list_append(msg->hdr_list, | |
329 create_header(HEAD_FROM, | |
330 "From: \"%s\" <%s@%s>\n", | |
331 msg->full_sender_name, | |
332 msg->return_path->local_part, | |
333 msg->return_path->domain)); | |
334 } else { | |
335 msg->hdr_list = g_list_append(msg->hdr_list, | |
336 create_header(HEAD_FROM, | |
337 "From: <%s@%s>\n", | |
338 msg->return_path->local_part, | |
339 msg->return_path->domain)); | |
340 } | |
341 } | |
342 if (!has_to_or_cc) { | |
343 DEBUG(3) debugf("no To: or Cc: header, hence adding " | |
344 "`To: undisclosed recipients:;'\n"); | |
345 msg->hdr_list = g_list_append(msg->hdr_list, | |
346 create_header(HEAD_TO, | |
347 "To: undisclosed-recipients:;\n")); | |
348 } | |
349 if (!has_date) { | |
350 DEBUG(3) debugf("adding 'Date:' header\n"); | |
351 msg->hdr_list = g_list_append(msg->hdr_list, | |
352 create_header(HEAD_DATE, "Date: %s\n", | |
353 rec_timestamp())); | |
354 } | |
355 if (!has_id) { | |
356 DEBUG(3) debugf("adding 'Message-ID:' header\n"); | |
357 msg->hdr_list = g_list_append(msg->hdr_list, | |
358 create_header(HEAD_MESSAGE_ID, | |
359 "Message-ID: <%s@%s>\n", | |
360 msg->uid, conf.host_name)); | |
361 } | |
362 | |
363 return AERR_OK; | |
364 } | |
365 | |
366 static void | |
367 add_received_hdr(message *msg) | |
368 { | |
369 gchar *for_string = NULL; | |
370 header *hdr = NULL; | |
371 address *addr; | |
372 | |
373 DEBUG(3) debugf("adding 'Received:' header\n"); | |
374 if (g_list_length(msg->rcpt_list) == 1) { | |
375 /* The `for' part only if exactly one rcpt is present */ | |
376 addr = (address *) (g_list_first(msg->rcpt_list)->data); | |
377 for_string = g_strdup_printf("\n\tfor %s", addr_string(addr)); | |
378 } | |
379 if (!msg->received_host) { | |
380 /* received locally */ | |
381 hdr = create_header(HEAD_RECEIVED, | |
382 "Received: by %s (%s %s, from userid %d)\n" | |
383 "\tid %s%s; %s\n", | |
384 conf.host_name, PACKAGE, VERSION, geteuid(), | |
385 msg->uid, | |
386 for_string ? for_string : "", rec_timestamp()); | |
387 } else { | |
388 /* received from remote */ | |
389 DEBUG(5) debugf("adding 'Received:' header (5)\n"); | |
390 hdr = create_header(HEAD_RECEIVED, | |
391 "Received: from %s\n" | |
392 "\tby %s with %s (%s %s)\n" | |
393 "\tid %s%s; %s\n", | |
394 msg->received_host, conf.host_name, | |
395 prot_names[msg->received_prot], PACKAGE, | |
396 VERSION, msg->uid, | |
397 for_string ? for_string : "", rec_timestamp()); | |
398 } | |
399 msg->hdr_list = g_list_prepend(msg->hdr_list, hdr); | |
400 if (for_string) { | |
401 g_free(for_string); | |
402 } | |
403 } | |
404 | |
182 accept_error | 405 accept_error |
183 accept_message_prepare(message *msg, guint flags) | 406 accept_message_prepare(message *msg, guint flags) |
184 { | 407 { |
185 struct passwd *passwd = NULL; | |
186 time_t rec_time = time(NULL); | |
187 | |
188 DEBUG(5) debugf("accept_message_prepare()\n"); | 408 DEBUG(5) debugf("accept_message_prepare()\n"); |
189 | 409 |
190 /* create unique message id */ | 410 /* generate unique message id */ |
191 msg->uid = g_malloc(14); | 411 msg->uid = g_malloc(14); |
192 string_base62(msg->uid, rec_time, 6); | 412 string_base62(msg->uid, time(NULL), 6); |
193 msg->uid[6] = '-'; | 413 msg->uid[6] = '-'; |
194 string_base62(msg->uid + 7, getpid(), 3); | 414 string_base62(msg->uid + 7, getpid(), 3); |
195 msg->uid[10] = '-'; | 415 msg->uid[10] = '-'; |
196 string_base62(msg->uid + 11, msg->transfer_id, 2); | 416 string_base62(msg->uid + 11, msg->transfer_id, 2); |
197 msg->uid[13] = '\0'; | 417 msg->uid[13] = '\0'; |
198 | 418 |
199 /* if local, get password entry and set return path if missing */ | 419 /* if local, get password entry and set return path if missing */ |
200 if (!msg->received_host) { | 420 if (!msg->received_host) { |
421 struct passwd *passwd = NULL; | |
422 | |
201 passwd = g_memdup(getpwuid(geteuid()), sizeof(struct passwd)); | 423 passwd = g_memdup(getpwuid(geteuid()), sizeof(struct passwd)); |
202 msg->ident = g_strdup(passwd->pw_name); | 424 msg->ident = g_strdup(passwd->pw_name); |
203 if (!msg->return_path) { | 425 if (!msg->return_path) { |
204 gchar *path = g_strdup_printf("<%s@%s>", passwd->pw_name, conf.host_name); | 426 gchar *path = g_strdup_printf("<%s@%s>", |
205 DEBUG(3) debugf("setting return_path for local accept: %s\n", path); | 427 passwd->pw_name, conf.host_name); |
428 DEBUG(3) debugf("setting return_path for local " | |
429 "accept: %s\n", path); | |
206 msg->return_path = create_address(path, TRUE); | 430 msg->return_path = create_address(path, TRUE); |
207 g_free(path); | 431 g_free(path); |
208 } | 432 } |
209 } | 433 } |
210 | 434 |
211 /* scan headers */ | 435 if (scan_headers(msg, flags) == AERR_NORCPT) { |
212 { | 436 return AERR_NORCPT; |
213 gboolean has_id = FALSE; | 437 } |
214 gboolean has_date = FALSE; | 438 |
215 gboolean has_sender = FALSE; | 439 /* after the hdrs are scanned because we need to know the rcpts */ |
216 gboolean has_from = FALSE; | 440 add_received_hdr(msg); |
217 gboolean has_to_or_cc = FALSE; | |
218 GList *hdr_node, *hdr_node_next; | |
219 header *hdr; | |
220 | |
221 for (hdr_node = g_list_first(msg->hdr_list); | |
222 hdr_node; | |
223 hdr_node = hdr_node_next) { | |
224 hdr_node_next = g_list_next(hdr_node); | |
225 hdr = ((header *) (hdr_node->data)); | |
226 DEBUG(5) debugf("scanning headers: %s", hdr->header); | |
227 switch (hdr->id) { | |
228 case HEAD_MESSAGE_ID: | |
229 has_id = TRUE; | |
230 break; | |
231 case HEAD_DATE: | |
232 has_date = TRUE; | |
233 break; | |
234 case HEAD_FROM: | |
235 has_from = TRUE; | |
236 break; | |
237 case HEAD_SENDER: | |
238 has_sender = TRUE; | |
239 break; | |
240 case HEAD_TO: | |
241 case HEAD_CC: | |
242 has_to_or_cc = TRUE; | |
243 /* fall through */ | |
244 case HEAD_BCC: | |
245 if (flags & ACC_RCPT_FROM_HEAD) { | |
246 /* -t option (see comment above) */ | |
247 DEBUG(5) debugf("hdr->value = %s\n", hdr->value); | |
248 if (hdr->value) { | |
249 msg->rcpt_list = addr_list_append_rfc822(msg->rcpt_list, hdr->value, conf.host_name); | |
250 } | |
251 } | |
252 if (hdr->id == HEAD_BCC) { | |
253 DEBUG(3) debugf("removing 'Bcc' header\n"); | |
254 msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node); | |
255 g_list_free_1(hdr_node); | |
256 destroy_header(hdr); | |
257 } | |
258 break; | |
259 case HEAD_ENVELOPE_TO: | |
260 if (flags & ACC_SAVE_ENVELOPE_TO) { | |
261 DEBUG(3) debugf("creating 'X-Orig-Envelope-To' header\n"); | |
262 msg->hdr_list = g_list_prepend(msg->hdr_list, create_header(HEAD_UNKNOWN, | |
263 "X-Orig-Envelope-To: %s", hdr->value)); | |
264 } | |
265 DEBUG(3) debugf("removing 'Envelope-To' header\n"); | |
266 msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node); | |
267 g_list_free_1(hdr_node); | |
268 destroy_header(hdr); | |
269 break; | |
270 case HEAD_RETURN_PATH: | |
271 if (flags & ACC_MAIL_FROM_HEAD) { | |
272 /* usually POP3 accept */ | |
273 msg->return_path = create_address_qualified(hdr->value, TRUE, msg->received_host); | |
274 DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path)); | |
275 } | |
276 DEBUG(3) debugf("removing 'Return-Path' header\n"); | |
277 msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node); | |
278 g_list_free_1(hdr_node); | |
279 destroy_header(hdr); | |
280 break; | |
281 default: | |
282 break; /* make compiler happy */ | |
283 } | |
284 } | |
285 | |
286 if (!msg->return_path) { | |
287 /* | |
288 ** TODO: do we still need this as we don't fetch | |
289 ** mail anymore? | |
290 ** This can happen for pop3 accept only and if no | |
291 ** Return-Path: header was given | |
292 */ | |
293 GList *hdr_list; | |
294 header *hdr; | |
295 | |
296 DEBUG(3) debugf("return_path == NULL\n"); | |
297 | |
298 hdr_list = find_header(msg->hdr_list, HEAD_SENDER, NULL); | |
299 if (!hdr_list) { | |
300 hdr_list = find_header(msg->hdr_list, HEAD_FROM, NULL); | |
301 } | |
302 if (hdr_list) { | |
303 gchar *addr; | |
304 hdr = (header *) (g_list_first(hdr_list)->data); | |
305 | |
306 DEBUG(5) debugf("hdr->value = '%s'\n", hdr->value); | |
307 | |
308 addr = g_strdup(hdr->value); | |
309 g_strchomp(addr); | |
310 | |
311 msg->return_path = create_address_qualified(addr, FALSE, msg->received_host); | |
312 if (msg->return_path) { | |
313 DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path)); | |
314 msg->hdr_list = g_list_append( msg->hdr_list, create_header(HEAD_UNKNOWN, "X-Warning: return path set from %s address\n", hdr->id == HEAD_SENDER ? "Sender:" : "From:")); | |
315 } | |
316 g_free(addr); | |
317 } | |
318 if (!msg->return_path) { | |
319 /* no Sender: or From: or | |
320 create_address_qualified failed */ | |
321 msg->return_path = create_address_qualified("postmaster", TRUE, conf.host_name); | |
322 DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path)); | |
323 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_UNKNOWN, "X-Warning: real return path is unknown\n")); | |
324 } | |
325 } | |
326 | |
327 /* here we should have our recipients, fail if not: */ | |
328 if (!msg->rcpt_list) { | |
329 logwrite(LOG_WARNING, "no recipients found in message\n"); | |
330 return AERR_NORCPT; | |
331 } | |
332 | |
333 if (!has_sender && !has_from) { | |
334 DEBUG(3) debugf("adding 'From:' header\n"); | |
335 if (msg->full_sender_name) { | |
336 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_FROM, "From: \"%s\" <%s@%s>\n", msg->full_sender_name, msg->return_path->local_part, msg->return_path->domain)); | |
337 } else { | |
338 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_FROM, "From: <%s@%s>\n", msg->return_path->local_part, msg->return_path->domain)); | |
339 } | |
340 } | |
341 if (!has_to_or_cc) { | |
342 DEBUG(3) debugf("no To: or Cc: header, hence adding `To: undisclosed recipients:;'\n"); | |
343 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_TO, "To: undisclosed-recipients:;\n")); | |
344 } | |
345 if (!has_date) { | |
346 DEBUG(3) debugf("adding 'Date:' header\n"); | |
347 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_DATE, "Date: %s\n", rec_timestamp())); | |
348 } | |
349 if (!has_id) { | |
350 DEBUG(3) debugf("adding 'Message-ID:' header\n"); | |
351 msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_MESSAGE_ID, "Message-ID: <%s@%s>\n", msg->uid, conf.host_name)); | |
352 } | |
353 } | |
354 | |
355 /* Received header: */ | |
356 /* At this point because we have to know the rcpts for the 'for' part */ | |
357 /* The `for' part will only be used if exactly one rcpt is present. */ | |
358 gchar *for_string = NULL; | |
359 header *hdr = NULL; | |
360 | |
361 DEBUG(3) debugf("adding 'Received:' header\n"); | |
362 | |
363 if (g_list_length(msg->rcpt_list) == 1) { | |
364 address *addr = (address *) (g_list_first(msg->rcpt_list)->data); | |
365 for_string = g_strdup_printf("\n\tfor %s", addr_string(addr)); | |
366 } | |
367 | |
368 if (!msg->received_host) { | |
369 /* received locally */ | |
370 hdr = create_header(HEAD_RECEIVED, | |
371 "Received: by %s (%s %s, from userid %d)\n\tid %s%s; %s\n", | |
372 conf.host_name, PACKAGE, VERSION, geteuid(), | |
373 msg->uid, for_string ? for_string : "", rec_timestamp()); | |
374 } else { | |
375 /* received from remote */ | |
376 DEBUG(5) debugf("adding 'Received:' header (5)\n"); | |
377 hdr = create_header(HEAD_RECEIVED, | |
378 "Received: from %s\n\tby %s with %s (%s %s)\n\tid %s%s; %s\n", | |
379 msg->received_host, | |
380 conf.host_name, prot_names[msg->received_prot], PACKAGE, | |
381 VERSION, msg->uid, for_string ? for_string : "", | |
382 rec_timestamp()); | |
383 } | |
384 msg->hdr_list = g_list_prepend(msg->hdr_list, hdr); | |
385 | |
386 if (for_string) | |
387 g_free(for_string); | |
388 | 441 |
389 return AERR_OK; | 442 return AERR_OK; |
390 } | 443 } |
391 | 444 |
392 accept_error | 445 accept_error |