Mercurial > masqmail
comparison src/deliver.c @ 280:72e377210d5e
heavy refactoring of deliver.c
I need to have closer looks in there; seems as if there are possibilies
to clean up
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Mon, 06 Dec 2010 18:07:01 -0300 |
parents | 5f9f3a65032e |
children | f10a56dc7481 |
comparison
equal
deleted
inserted
replaced
279:1aa107c6b1e5 | 280:72e377210d5e |
---|---|
40 address *rcpt = (address *) (rcpt_node->data); | 40 address *rcpt = (address *) (rcpt_node->data); |
41 | 41 |
42 if (addr_is_defered(rcpt)) { | 42 if (addr_is_defered(rcpt)) { |
43 if ((now - msg->received_time) >= conf.max_defer_time) { | 43 if ((now - msg->received_time) >= conf.max_defer_time) { |
44 addr_mark_failed(rcpt); | 44 addr_mark_failed(rcpt); |
45 } else | 45 } else { |
46 defered_list = g_list_prepend(defered_list, rcpt); | 46 defered_list = g_list_prepend(defered_list, rcpt); |
47 } | 47 } |
48 if (addr_is_failed(rcpt)) | 48 } |
49 if (addr_is_failed(rcpt)) { | |
49 failed_list = g_list_prepend(failed_list, rcpt); | 50 failed_list = g_list_prepend(failed_list, rcpt); |
50 } | 51 } |
51 if (failed_list != NULL) { | 52 } |
53 if (failed_list) { | |
52 ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args); | 54 ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args); |
53 g_list_free(failed_list); | 55 g_list_free(failed_list); |
54 } | 56 } |
55 if (defered_list != NULL) { | 57 if (defered_list) { |
56 ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args); | 58 ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args); |
57 g_list_free(defered_list); | 59 g_list_free(defered_list); |
58 } | 60 } |
59 va_end(args); | 61 va_end(args); |
60 return ok_fail && ok_warn; | 62 return ok_fail && ok_warn; |
62 | 64 |
63 static gint | 65 static gint |
64 _g_list_strcasecmp(gconstpointer a, gconstpointer b) | 66 _g_list_strcasecmp(gconstpointer a, gconstpointer b) |
65 { | 67 { |
66 return (gint) strcasecmp(a, b); | 68 return (gint) strcasecmp(a, b); |
69 } | |
70 | |
71 gboolean | |
72 deliver_local_mbox(message* msg, GList* hdr_list, address* rcpt, address* env_addr) | |
73 { | |
74 DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); | |
75 if (append_file(msg, hdr_list, rcpt->local_part)) { | |
76 if (env_addr != rcpt) { | |
77 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", msg->uid, rcpt->local_part, rcpt->domain, env_addr->local_part, env_addr->domain); | |
78 } else { | |
79 logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", msg->uid, rcpt->local_part, rcpt->domain); | |
80 } | |
81 addr_mark_delivered(rcpt); | |
82 return TRUE; | |
83 } | |
84 | |
85 /* prevents 'Resource temporarily unavailable (11)' */ | |
86 if (errno != EAGAIN) { | |
87 addr_mark_failed(rcpt); | |
88 } else { | |
89 addr_mark_defered(rcpt); | |
90 } | |
91 return FALSE; | |
92 } | |
93 | |
94 gboolean | |
95 deliver_local_pipe(message* msg, GList* hdr_list, address* rcpt, address* env_addr) | |
96 { | |
97 guint flags; | |
98 | |
99 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); | |
100 | |
101 flags = (conf.pipe_fromline) ? MSGSTR_FROMLINE : 0; | |
102 flags |= (conf.pipe_fromhack) ? MSGSTR_FROMHACK : 0; | |
103 if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), flags)) { | |
104 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", | |
105 msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); | |
106 addr_mark_delivered(rcpt); | |
107 return TRUE; | |
108 } | |
109 | |
110 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { | |
111 addr_mark_failed(rcpt); | |
112 } else { | |
113 addr_mark_defered(rcpt); | |
114 /* has no effect yet, except that mail remains in spool */ | |
115 } | |
116 return FALSE; | |
117 } | |
118 | |
119 gboolean | |
120 deliver_local_mda(message* msg, GList* hdr_list, address* rcpt, address* env_addr) | |
121 { | |
122 gboolean ok = FALSE; | |
123 gchar *cmd = g_malloc(256); | |
124 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); | |
125 guint flags; | |
126 | |
127 DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); | |
128 | |
129 if (!expand(var_table, conf.mda, cmd, 256)) { | |
130 logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); | |
131 destroy_table(var_table); | |
132 return FALSE; | |
133 } | |
134 | |
135 flags = (conf.mda_fromline) ? MSGSTR_FROMLINE : 0; | |
136 flags |= (conf.mda_fromhack) ? MSGSTR_FROMHACK : 0; | |
137 if (pipe_out(msg, hdr_list, rcpt, cmd, flags)) { | |
138 logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", | |
139 msg->uid, rcpt->local_part, rcpt->domain, cmd); | |
140 addr_mark_delivered(rcpt); | |
141 ok = TRUE; | |
142 } else if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { | |
143 addr_mark_failed(rcpt); | |
144 } else { | |
145 addr_mark_defered(rcpt); | |
146 /* has no effect yet, except that mail remains in spool */ | |
147 } | |
148 | |
149 destroy_table(var_table); | |
150 return ok; | |
67 } | 151 } |
68 | 152 |
69 gboolean | 153 gboolean |
70 deliver_local(msg_out * msgout) | 154 deliver_local(msg_out * msgout) |
71 { | 155 { |
72 message *msg = msgout->msg; | 156 message *msg = msgout->msg; |
73 GList *rcpt_list = msgout->rcpt_list; | 157 GList *rcpt_list = msgout->rcpt_list; |
74 GList *rcpt_node; | 158 GList *rcpt_node; |
75 gboolean ok = TRUE, flag = FALSE, ok_fail = FALSE; | 159 gboolean ok = FALSE, flag = FALSE, ok_fail = FALSE; |
76 | 160 |
77 DEBUG(5) debugf("deliver_local entered\n"); | 161 DEBUG(5) debugf("deliver_local entered\n"); |
78 | 162 |
79 flag = (msg->data_list == NULL); | 163 flag = (msg->data_list == NULL); |
80 if (flag) { | 164 if (flag && !spool_read_data(msg)) { |
81 if (!(ok = spool_read_data(msg))) { | 165 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); |
82 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); | 166 return FALSE; |
83 } | 167 } |
84 } | 168 |
85 if (!ok) | |
86 return FALSE; | |
87 | |
88 ok = FALSE; | |
89 for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { | 169 for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { |
90 GList *hdr_list; | 170 GList *hdr_list; |
91 address *rcpt = (address *) (rcpt_node->data); | 171 address *rcpt = (address *) (rcpt_node->data); |
92 address *env_addr = addr_find_ancestor(rcpt); | 172 address *env_addr = addr_find_ancestor(rcpt); |
93 address *ret_path = msg->return_path; | 173 address *ret_path = msg->return_path; |
94 header *retpath_hdr, *envto_hdr; | 174 header *retpath_hdr, *envto_hdr; |
95 | 175 |
96 /* we need a private copy of the hdr list because we add headers here that belong to the rcpt only. | 176 /* we need a private copy of the hdr list because we add headers |
97 g_list_copy copies only the nodes, so it is safe to g_list_free it */ | 177 here that belong to the rcpt only. g_list_copy copies only |
178 the nodes, so it is safe to g_list_free it */ | |
98 hdr_list = g_list_copy(msg->hdr_list); | 179 hdr_list = g_list_copy(msg->hdr_list); |
99 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); | 180 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); |
100 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); | 181 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); |
101 | 182 |
102 hdr_list = g_list_prepend(hdr_list, envto_hdr); | 183 hdr_list = g_list_prepend(hdr_list, envto_hdr); |
103 hdr_list = g_list_prepend(hdr_list, retpath_hdr); | 184 hdr_list = g_list_prepend(hdr_list, retpath_hdr); |
104 | 185 |
105 if (rcpt->local_part[0] == '|') { | 186 if (rcpt->local_part[0] == '|') { |
106 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); | 187 /* probably for expanded aliases, but why not done |
107 if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), | 188 like with the mda? //meillo 2010-12-06 */ |
108 (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) | 189 if (deliver_local_pipe(msg, hdr_list, rcpt, env_addr)) { |
109 | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) { | |
110 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", | |
111 msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); | |
112 addr_mark_delivered(rcpt); | |
113 ok = TRUE; | 190 ok = TRUE; |
114 } else { | |
115 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { | |
116 addr_mark_failed(rcpt); | |
117 } else { | |
118 addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ | |
119 } | |
120 } | 191 } |
121 } else { | 192 } else { |
122 /* figure out which mailbox type should be used for this user */ | 193 /* figure out which mailbox type should be used for this user */ |
123 gchar *user = rcpt->local_part; | 194 gchar *user = rcpt->local_part; |
124 gchar *mbox_type = conf.mbox_default; | 195 gchar *mbox_type = conf.mbox_default; |
125 | 196 |
126 if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp) != NULL) | 197 if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp)) { |
127 mbox_type = "mbox"; | 198 mbox_type = "mbox"; |
128 else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp) != NULL) | 199 } else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp)) { |
129 mbox_type = "mda"; | 200 mbox_type = "mda"; |
201 } | |
130 | 202 |
131 if (strcmp(mbox_type, "mbox") == 0) { | 203 if (strcmp(mbox_type, "mbox") == 0) { |
132 DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); | 204 if (deliver_local_mbox(msg, hdr_list, rcpt, env_addr)) { |
133 if (append_file(msg, hdr_list, rcpt->local_part)) { | |
134 if (env_addr != rcpt) { | |
135 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", | |
136 msg->uid, rcpt->local_part, rcpt->domain, | |
137 env_addr->local_part, env_addr->domain); | |
138 } else { | |
139 logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", | |
140 msg->uid, rcpt->local_part, rcpt->domain); | |
141 } | |
142 addr_mark_delivered(rcpt); | |
143 ok = TRUE; | 205 ok = TRUE; |
144 } else { | |
145 if (errno != EAGAIN) { /* prevents 'Resource temporarily unavailable (11)' */ | |
146 addr_mark_failed(rcpt); | |
147 } else { | |
148 addr_mark_defered(rcpt); | |
149 } | |
150 } | 206 } |
151 | |
152 } else if (strcmp(mbox_type, "mda") == 0) { | 207 } else if (strcmp(mbox_type, "mda") == 0) { |
153 if (conf.mda) { | 208 if (conf.mda) { |
154 gchar *cmd = g_malloc(256); | 209 if (deliver_local_mda(msg, hdr_list, rcpt, env_addr)) { |
155 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); | 210 ok = TRUE; |
156 | 211 } |
157 DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); | 212 } else { |
158 | |
159 if (expand(var_table, conf.mda, cmd, 256)) { | |
160 | |
161 if (pipe_out(msg, hdr_list, rcpt, cmd, (conf.mda_fromline ? MSGSTR_FROMLINE : 0) | |
162 | (conf.mda_fromhack ? MSGSTR_FROMHACK : 0))) { | |
163 logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", | |
164 msg->uid, rcpt->local_part, rcpt->domain, cmd); | |
165 addr_mark_delivered(rcpt); | |
166 ok = TRUE; | |
167 } else { | |
168 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { | |
169 addr_mark_failed(rcpt); | |
170 } else { | |
171 addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ | |
172 } | |
173 } | |
174 } else | |
175 logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); | |
176 | |
177 destroy_table(var_table); | |
178 } else | |
179 logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); | 213 logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); |
180 } else | 214 } |
215 | |
216 } else { | |
181 logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type); | 217 logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type); |
218 } | |
182 } | 219 } |
183 | 220 |
184 destroy_header(retpath_hdr); | 221 destroy_header(retpath_hdr); |
185 destroy_header(envto_hdr); | 222 destroy_header(envto_hdr); |
186 | 223 |
187 g_list_free(hdr_list); | 224 g_list_free(hdr_list); |
188 } | 225 } |
189 ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno); | 226 ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno); |
190 | 227 |
191 if (flag) | 228 if (flag) { |
192 msg_free_data(msg); | 229 msg_free_data(msg); |
193 if (ok || ok_fail) | 230 } |
231 if (ok || ok_fail) { | |
194 deliver_finish(msgout); | 232 deliver_finish(msgout); |
233 } | |
195 | 234 |
196 return ok; | 235 return ok; |
197 } | 236 } |
198 | 237 |
199 /* make a list of rcpt's of a message that are local return a new copy of the list */ | 238 /* make a list of rcpt's of a message that are local return a new copy of the list */ |
234 return FALSE; | 273 return FALSE; |
235 } | 274 } |
236 | 275 |
237 foreach(msgout_list, msgout_node) { | 276 foreach(msgout_list, msgout_node) { |
238 msg_out *msgout = (msg_out *) (msgout_node->data); | 277 msg_out *msgout = (msg_out *) (msgout_node->data); |
239 gboolean flag, ok_msg = TRUE, ok_fail = FALSE; | 278 gboolean flag, ok_fail = FALSE; |
240 message *msg = msgout->msg; | 279 message *msg = msgout->msg; |
241 GList *rcpt_node, *rcpt_list = msgout->rcpt_list; | 280 GList *rcpt_node, *rcpt_list = msgout->rcpt_list; |
242 | 281 |
243 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); | 282 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); |
244 | 283 |
245 flag = (msg->data_list == NULL); | 284 flag = (msg->data_list == NULL); |
246 if (flag) { | 285 if (flag && !spool_read_data(msg)) { |
247 if (!(ok_msg = spool_read_data(msg))) { | 286 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); |
248 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); | |
249 } | |
250 } | |
251 if (!ok_msg) | |
252 continue; | 287 continue; |
288 } | |
253 | 289 |
254 ok = FALSE; | 290 ok = FALSE; |
255 foreach(rcpt_list, rcpt_node) { | 291 foreach(rcpt_list, rcpt_node) { |
256 address *rcpt = (address *) (rcpt_node->data); | 292 address *rcpt = (address *) (rcpt_node->data); |
257 gchar *cmd = g_malloc(256); | 293 gchar *cmd = g_malloc(256); |
258 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); | 294 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); |
259 | 295 |
260 DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", msg->uid, rcpt->local_part, rcpt->domain); | 296 DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", msg->uid, rcpt->local_part, rcpt->domain); |
261 | 297 |
262 if (expand(var_table, route->pipe, cmd, 256)) { | 298 if (!expand(var_table, route->pipe, cmd, 256)) { |
299 logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); | |
300 } else { | |
263 | 301 |
264 if (pipe_out(msg, msg->hdr_list, rcpt, cmd, (route->pipe_fromline ? MSGSTR_FROMLINE : 0) | 302 if (pipe_out(msg, msg->hdr_list, rcpt, cmd, (route->pipe_fromline ? MSGSTR_FROMLINE : 0) |
265 | (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))) { | 303 | (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))) { |
266 logwrite(LOG_NOTICE, "%s => %s@%s with pipe (cmd = '%s')\n", | 304 logwrite(LOG_NOTICE, "%s => %s@%s with pipe (cmd = '%s')\n", |
267 msg->uid, rcpt->local_part, rcpt->domain, cmd); | 305 msg->uid, rcpt->local_part, rcpt->domain, cmd); |
274 addr_mark_failed(rcpt); | 312 addr_mark_failed(rcpt); |
275 } else { | 313 } else { |
276 addr_mark_defered(rcpt); | 314 addr_mark_defered(rcpt); |
277 } | 315 } |
278 } | 316 } |
279 } else | 317 } |
280 logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); | |
281 | 318 |
282 destroy_table(var_table); | 319 destroy_table(var_table); |
283 } | 320 } |
284 ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno)); | 321 ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno)); |
285 | 322 |
286 if (flag) | 323 if (flag) { |
287 msg_free_data(msg); | 324 msg_free_data(msg); |
288 | 325 } |
289 if (ok || ok_fail) | 326 if (ok || ok_fail) { |
290 deliver_finish(msgout); | 327 deliver_finish(msgout); |
291 } | 328 } |
292 | 329 } |
293 return ok; | 330 |
294 } | 331 return ok; |
295 | 332 } |
296 /* deliver list of messages to one host and finishes them if the message was delivered to at least one rcpt. | 333 |
334 /* deliver list of messages to one host and finishes them if the message was | |
335 delivered to at least one rcpt. | |
297 Returns TRUE if at least one msg was delivered to at least one rcpt. | 336 Returns TRUE if at least one msg was delivered to at least one rcpt. |
298 */ | 337 */ |
299 gboolean | 338 gboolean |
300 deliver_msglist_host_smtp(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) | 339 deliver_msglist_host_smtp(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) |
301 { | 340 { |
303 GList *msgout_node; | 342 GList *msgout_node; |
304 smtp_base *psb; | 343 smtp_base *psb; |
305 gint port = 25; | 344 gint port = 25; |
306 | 345 |
307 /* paranoid check: */ | 346 /* paranoid check: */ |
308 if (msgout_list == NULL) { | 347 if (!msgout_list) { |
309 logwrite(LOG_ALERT, "Ooops: empty list of messages in deliver_msglist_host()\n"); | 348 logwrite(LOG_ALERT, "Ooops: empty list of messages in deliver_msglist_host()\n"); |
310 return FALSE; | 349 return FALSE; |
311 } | 350 } |
312 | 351 |
313 if (host == NULL) { | 352 if (!host) { |
314 /* XXX: what if mail_host isn't set? Is this possible? */ | 353 /* XXX: what if mail_host isn't set? Is this possible? */ |
315 host = route->mail_host->address; | 354 host = route->mail_host->address; |
316 port = route->mail_host->port; | 355 port = route->mail_host->port; |
317 } | 356 } |
318 | 357 |
319 if ((psb = (route->wrapper ? smtp_out_open_child(route->wrapper) : smtp_out_open(host, port, res_list)))) { | 358 if (route->wrapper) { |
320 | 359 psb = smtp_out_open_child(route->wrapper); |
321 if (route->wrapper) { | |
322 /* it seems as if the remote_host is only set for logging | |
323 /* XXX: this could probably be moved into smtp_out_open_child() */ | |
324 psb->remote_host = host; | |
325 } | |
326 | |
327 set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); | |
328 | |
329 #ifdef ENABLE_AUTH | |
330 if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) | |
331 set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); | |
332 #endif | |
333 if (smtp_out_init(psb, route->instant_helo)) { | |
334 | |
335 if (!route->do_pipelining) | |
336 psb->use_pipelining = FALSE; | |
337 | |
338 foreach(msgout_list, msgout_node) { | |
339 msg_out *msgout = (msg_out *) (msgout_node->data); | |
340 gboolean flag, ok_msg = FALSE, ok_fail = FALSE; | |
341 message *msg = msgout->msg; | |
342 | |
343 /* we may have to read the data at this point and remember if we did */ | |
344 flag = (msg->data_list == NULL); | |
345 if (flag) { | |
346 if (!spool_read_data(msg)) { | |
347 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); | |
348 break; | |
349 } | |
350 } | |
351 | |
352 smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); | |
353 | |
354 ok_fail = delivery_failures(msg, msgout->rcpt_list, | |
355 "while connected with %s, the server replied\n\t%s", host, psb->buffer); | |
356 | |
357 if ((psb->error == smtp_eof) | |
358 || (psb->error == smtp_timeout)) { | |
359 /* connection lost */ | |
360 break; | |
361 } else if (psb->error != smtp_ok) { | |
362 if (g_list_next(msgout_node) != NULL) | |
363 if (!smtp_out_rset(psb)) | |
364 break; | |
365 } | |
366 ok_msg = (psb->error == smtp_ok); | |
367 | |
368 if (flag) | |
369 msg_free_data(msg); | |
370 if (ok_msg) | |
371 ok = TRUE; | |
372 if (ok_msg || ok_fail) { | |
373 deliver_finish(msgout); | |
374 } | |
375 } | |
376 if (psb->error == smtp_ok || (psb->error == smtp_fail) | |
377 || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { | |
378 smtp_out_quit(psb); | |
379 } | |
380 } else { | |
381 /* smtp_out_init() failed */ | |
382 if ((psb->error == smtp_fail) || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { | |
383 smtp_out_quit(psb); | |
384 | |
385 foreach(msgout_list, msgout_node) { | |
386 msg_out *msgout = (msg_out *) (msgout_node->data); | |
387 smtp_out_mark_rcpts(psb, msgout->rcpt_list); | |
388 | |
389 if (delivery_failures(msgout->msg, msgout->rcpt_list, | |
390 "while connected with %s, the server replied\n\t%s", host, psb->buffer)) | |
391 deliver_finish(msgout); | |
392 } | |
393 } | |
394 } | |
395 destroy_smtpbase(psb); | |
396 } else { | 360 } else { |
361 psb = smtp_out_open(host, port, res_list); | |
362 } | |
363 | |
364 if (!psb) { | |
397 /* smtp_out_open() failed */ | 365 /* smtp_out_open() failed */ |
398 foreach(msgout_list, msgout_node) { | 366 foreach(msgout_list, msgout_node) { |
399 msg_out *msgout = (msg_out *) (msgout_node->data); | 367 msg_out *msgout = (msg_out *) (msgout_node->data); |
400 GList *rcpt_node; | 368 GList *rcpt_node; |
401 | 369 |
402 for (rcpt_node = g_list_first(msgout->rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { | 370 for (rcpt_node = g_list_first(msgout->rcpt_list); |
371 rcpt_node; | |
372 rcpt_node = g_list_next(rcpt_node)) { | |
403 address *rcpt = (address *) (rcpt_node->data); | 373 address *rcpt = (address *) (rcpt_node->data); |
374 gboolean ret = FALSE; | |
404 | 375 |
405 addr_unmark_delivered(rcpt); | 376 addr_unmark_delivered(rcpt); |
406 if (route->connect_error_fail) { | 377 if (route->connect_error_fail) { |
407 addr_mark_failed(rcpt); | 378 addr_mark_failed(rcpt); |
408 } else { | 379 } else { |
409 addr_mark_defered(rcpt); | 380 addr_mark_defered(rcpt); |
410 } | 381 } |
411 if (route->wrapper | 382 if (route->wrapper) { |
412 ? delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", | 383 ret = delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", strerror(errno)); |
413 strerror(errno)) | 384 } else { |
414 : delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", | 385 ret = delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno)); |
415 host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) | 386 } |
387 if (ret) { | |
416 deliver_finish(msgout); | 388 deliver_finish(msgout); |
417 } | 389 } |
418 } | 390 } |
419 } | 391 } |
392 return ok; | |
393 } | |
394 | |
395 | |
396 if (route->wrapper) { | |
397 /* it seems as if the remote_host is only set for logging | |
398 /* XXX: this could probably be moved into smtp_out_open_child() */ | |
399 psb->remote_host = host; | |
400 } | |
401 | |
402 set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); | |
403 | |
404 #ifdef ENABLE_AUTH | |
405 if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) { | |
406 set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); | |
407 } | |
408 #endif | |
409 if (!smtp_out_init(psb, route->instant_helo)) { | |
410 /* smtp_out_init() failed */ | |
411 if ((psb->error==smtp_fail) || (psb->error==smtp_trylater) || (psb->error==smtp_syntax)) { | |
412 smtp_out_quit(psb); | |
413 | |
414 foreach(msgout_list, msgout_node) { | |
415 msg_out *msgout = (msg_out *) (msgout_node->data); | |
416 smtp_out_mark_rcpts(psb, msgout->rcpt_list); | |
417 | |
418 if (delivery_failures(msgout->msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer)) { | |
419 deliver_finish(msgout); | |
420 } | |
421 } | |
422 } | |
423 destroy_smtpbase(psb); | |
424 return ok; | |
425 } | |
426 | |
427 if (!route->do_pipelining) { | |
428 psb->use_pipelining = FALSE; | |
429 } | |
430 | |
431 foreach(msgout_list, msgout_node) { | |
432 msg_out *msgout = (msg_out *) (msgout_node->data); | |
433 gboolean flag, ok_msg = FALSE, ok_fail = FALSE; | |
434 message *msg = msgout->msg; | |
435 | |
436 /* we may have to read the data at this point and remember if we did */ | |
437 flag = (msg->data_list == NULL); | |
438 if (flag && !spool_read_data(msg)) { | |
439 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); | |
440 break; | |
441 } | |
442 | |
443 smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); | |
444 | |
445 ok_fail = delivery_failures(msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer); | |
446 | |
447 if ((psb->error == smtp_eof) || (psb->error == smtp_timeout)) { | |
448 /* connection lost */ | |
449 break; | |
450 } else if (psb->error != smtp_ok) { | |
451 if (g_list_next(msgout_node) && !smtp_out_rset(psb)) { | |
452 break; | |
453 } | |
454 } | |
455 ok_msg = (psb->error == smtp_ok); | |
456 | |
457 if (flag) { | |
458 msg_free_data(msg); | |
459 } | |
460 if (ok_msg) { | |
461 ok = TRUE; | |
462 } | |
463 if (ok_msg || ok_fail) { | |
464 deliver_finish(msgout); | |
465 } | |
466 } | |
467 if (psb->error == smtp_ok || (psb->error == smtp_fail) | |
468 || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { | |
469 smtp_out_quit(psb); | |
470 } | |
471 destroy_smtpbase(psb); | |
420 return ok; | 472 return ok; |
421 } | 473 } |
422 | 474 |
423 gboolean | 475 gboolean |
424 deliver_msglist_host(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) | 476 deliver_msglist_host(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) |
437 */ | 489 */ |
438 gboolean | 490 gboolean |
439 deliver_route_msgout_list(connect_route * route, GList * msgout_list) | 491 deliver_route_msgout_list(connect_route * route, GList * msgout_list) |
440 { | 492 { |
441 gboolean ok = FALSE; | 493 gboolean ok = FALSE; |
494 GList *mo_ph_list; | |
495 GList *mo_ph_node; | |
442 | 496 |
443 DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); | 497 DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); |
444 | 498 |
445 if (route->mail_host) { | 499 if (route->mail_host) { |
446 /* this is easy... deliver everything to a smart host for relay */ | 500 /* this is easy... deliver everything to a smart host for relay */ |
447 if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list)) | 501 return deliver_msglist_host(route, msgout_list, NULL, route->resolve_list); |
502 } | |
503 | |
504 /* this is not easy... */ | |
505 | |
506 mo_ph_list = route_msgout_list(route, msgout_list); | |
507 /* okay, now we have ordered our messages by the hosts. */ | |
508 if (!mo_ph_list) { | |
509 return FALSE; | |
510 } | |
511 | |
512 /* TODO: It would be nice to be able to fork for each host. | |
513 We cannot do that yet because of complications with finishing the | |
514 messages. Threads could be a solution because they use the same | |
515 memory. But we are not thread safe yet... | |
516 */ | |
517 foreach(mo_ph_list, mo_ph_node) { | |
518 msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); | |
519 if (deliver_msglist_host(route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) { | |
448 ok = TRUE; | 520 ok = TRUE; |
449 | 521 } |
450 } else { | 522 destroy_msgout_perhost(mo_ph); |
451 /* this is not easy... */ | 523 } |
452 GList *mo_ph_list; | 524 g_list_free(mo_ph_list); |
453 | |
454 mo_ph_list = route_msgout_list(route, msgout_list); | |
455 /* okay, now we have ordered our messages by the hosts. */ | |
456 if (mo_ph_list != NULL) { | |
457 GList *mo_ph_node; | |
458 /* TODO: It would be nice to be able to fork for each host. | |
459 We cannot do that yet because of complications with finishing the | |
460 messages. Threads could be a solution because they use the same | |
461 memory. But we are not thread safe yet... | |
462 */ | |
463 foreach(mo_ph_list, mo_ph_node) { | |
464 msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); | |
465 if (deliver_msglist_host (route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) | |
466 ok = TRUE; | |
467 | |
468 destroy_msgout_perhost(mo_ph); | |
469 } | |
470 g_list_free(mo_ph_list); | |
471 } | |
472 } | |
473 return ok; | 525 return ok; |
474 } | 526 } |
475 | 527 |
476 /* | 528 /* |
477 calls route_prepare_msg() | 529 calls route_prepare_msg() |
490 msg_out *msgout = (msg_out *) (msgout_node->data); | 542 msg_out *msgout = (msg_out *) (msgout_node->data); |
491 msg_out *msgout_cloned = clone_msg_out(msgout); | 543 msg_out *msgout_cloned = clone_msg_out(msgout); |
492 GList *rcpt_list_non_delivered = NULL; | 544 GList *rcpt_list_non_delivered = NULL; |
493 GList *rcpt_node; | 545 GList *rcpt_node; |
494 | 546 |
495 /* we have to delete already delivered rcpt's because a previous route may have delivered to it */ | 547 /* we have to delete already delivered rcpt's because a |
548 previous route may have delivered to it */ | |
496 foreach(msgout_cloned->rcpt_list, rcpt_node) { | 549 foreach(msgout_cloned->rcpt_list, rcpt_node) { |
497 address *rcpt = (address *) (rcpt_node->data); | 550 address *rcpt = (address *) (rcpt_node->data); |
498 /* failed addresses already have been bounced - there should be a better way to handle those. */ | 551 /* failed addresses already have been bounced; |
552 there should be a better way to handle those. */ | |
499 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) | 553 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) |
500 && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) | 554 && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) { |
501 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); | 555 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); |
556 } | |
502 } | 557 } |
503 g_list_free(msgout_cloned->rcpt_list); | 558 g_list_free(msgout_cloned->rcpt_list); |
504 msgout_cloned->rcpt_list = rcpt_list_non_delivered; | 559 msgout_cloned->rcpt_list = rcpt_list_non_delivered; |
505 | 560 |
506 if (msgout_cloned->rcpt_list) { | 561 if (!msgout_cloned->rcpt_list) { |
507 if (route_is_allowed_mail_local(route, msgout->msg->return_path) | |
508 && route_is_allowed_return_path(route, msgout->msg-> return_path)) { | |
509 GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; | |
510 msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); | |
511 | |
512 if (rcpt_list_allowed != NULL) { | |
513 logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); | |
514 | |
515 g_list_free(msgout_cloned->rcpt_list); | |
516 msgout_cloned->rcpt_list = rcpt_list_allowed; | |
517 | |
518 if (route->last_route) { | |
519 GList *rcpt_node; | |
520 foreach(msgout_cloned->rcpt_list, rcpt_node) { | |
521 address *rcpt = (address *) (rcpt_node->data); | |
522 rcpt->flags |= ADDR_FLAG_LAST_ROUTE; | |
523 } | |
524 } | |
525 | |
526 route_prepare_msgout(route, msgout_cloned); | |
527 msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); | |
528 } else | |
529 destroy_msg_out(msgout_cloned); | |
530 } else | |
531 destroy_msg_out(msgout_cloned); | |
532 } else | |
533 destroy_msg_out(msgout_cloned); | 562 destroy_msg_out(msgout_cloned); |
534 } | 563 continue; |
535 | 564 } |
536 if (msgout_list_deliver != NULL) { | 565 |
537 if (deliver_route_msgout_list(route, msgout_list_deliver)) | 566 if (!route_is_allowed_mail_local(route, msgout->msg->return_path) |
567 || !route_is_allowed_return_path(route, msgout->msg-> return_path)) { | |
568 destroy_msg_out(msgout_cloned); | |
569 continue; | |
570 } | |
571 | |
572 GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; | |
573 msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); | |
574 | |
575 if (!rcpt_list_allowed) { | |
576 destroy_msg_out(msgout_cloned); | |
577 continue; | |
578 } | |
579 logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); | |
580 | |
581 g_list_free(msgout_cloned->rcpt_list); | |
582 msgout_cloned->rcpt_list = rcpt_list_allowed; | |
583 | |
584 if (route->last_route) { | |
585 GList *rcpt_node; | |
586 foreach(msgout_cloned->rcpt_list, rcpt_node) { | |
587 address *rcpt = (address *) (rcpt_node->data); | |
588 rcpt->flags |= ADDR_FLAG_LAST_ROUTE; | |
589 } | |
590 } | |
591 | |
592 route_prepare_msgout(route, msgout_cloned); | |
593 msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); | |
594 } | |
595 | |
596 if (msgout_list_deliver) { | |
597 if (deliver_route_msgout_list(route, msgout_list_deliver)) { | |
538 ok = TRUE; | 598 ok = TRUE; |
599 } | |
539 destroy_msg_out_list(msgout_list_deliver); | 600 destroy_msg_out_list(msgout_list_deliver); |
540 } | 601 } |
541 return ok; | 602 return ok; |
542 } | 603 } |
543 | 604 |
550 GList *rcpt_node; | 611 GList *rcpt_node; |
551 message *msg = msgout->msg; | 612 message *msg = msgout->msg; |
552 | 613 |
553 foreach(msgout->rcpt_list, rcpt_node) { | 614 foreach(msgout->rcpt_list, rcpt_node) { |
554 address *rcpt = (address *) (rcpt_node->data); | 615 address *rcpt = (address *) (rcpt_node->data); |
555 if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) | 616 if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) { |
556 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); | 617 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); |
557 } | 618 } |
558 } | 619 } |
559 | 620 } |
560 /* after delivery attempts, we check if there are any rcpt addresses left in the message. | 621 |
561 If all addresses have been completed, the spool files will be deleted, | 622 /* after delivery attempts, we check if there are any rcpt addresses left in |
562 otherwise the header spool will be written back. | 623 the message. If all addresses have been completed, the spool files will be |
563 We never changed the data spool, so there is no need to write that back. | 624 deleted, otherwise the header spool will be written back. We never changed |
625 the data spool, so there is no need to write that back. | |
564 | 626 |
565 returns TRUE if all went well. | 627 returns TRUE if all went well. |
566 */ | 628 */ |
567 gboolean | 629 gboolean |
568 deliver_finish(msg_out * msgout) | 630 deliver_finish(msg_out * msgout) |
569 { | 631 { |
570 GList *rcpt_node; | 632 GList *rcpt_node; |
571 gboolean ok = FALSE; | |
572 message *msg = msgout->msg; | 633 message *msg = msgout->msg; |
573 gboolean finished = TRUE; | 634 gboolean finished = TRUE; |
574 | 635 |
575 update_non_rcpt_list(msgout); | 636 update_non_rcpt_list(msgout); |
576 | 637 |
577 /* we NEVER made copies of the addresses, flags affecting addresses | 638 /* we NEVER made copies of the addresses, flags affecting addresses |
578 were always set on the original address structs */ | 639 were always set on the original address structs */ |
579 foreach(msg->rcpt_list, rcpt_node) { | 640 foreach(msg->rcpt_list, rcpt_node) { |
580 address *rcpt = (address *) (rcpt_node->data); | 641 address *rcpt = (address *) (rcpt_node->data); |
581 if (!addr_is_finished_children(rcpt)) | 642 if (!addr_is_finished_children(rcpt)) { |
582 finished = FALSE; | 643 finished = FALSE; |
583 else { | 644 } else { |
584 /* if ALL children have been delivered, mark parent as delivered. | 645 /* if ALL children have been delivered, mark parent as |
585 if there is one or more not delivered, it must have failed, we mark the parent as failed as well. | 646 delivered. if there is one or more not delivered, |
647 it must have failed, we mark the parent as failed | |
648 as well. | |
586 */ | 649 */ |
587 if (addr_is_delivered_children(rcpt)) { | 650 if (addr_is_delivered_children(rcpt)) { |
588 addr_mark_delivered(rcpt); | 651 addr_mark_delivered(rcpt); |
589 } else { | 652 } else { |
590 addr_mark_failed(rcpt); | 653 addr_mark_failed(rcpt); |
591 } | 654 } |
592 } | 655 } |
593 } | 656 } |
594 | 657 |
595 if (!finished) { | 658 if (finished) { |
596 /* one not delivered address was found */ | 659 if (spool_delete_all(msg)) { |
597 if (spool_write(msg, FALSE)) { | |
598 ok = TRUE; | |
599 DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); | |
600 } else | |
601 logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); | |
602 } else { | |
603 ok = spool_delete_all(msg); | |
604 if (ok) | |
605 logwrite(LOG_NOTICE, "%s completed.\n", msg->uid); | 660 logwrite(LOG_NOTICE, "%s completed.\n", msg->uid); |
606 } | 661 return TRUE; |
607 return ok; | 662 } |
663 return FALSE; | |
664 } | |
665 | |
666 /* one not delivered address was found */ | |
667 if (!spool_write(msg, FALSE)) { | |
668 logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); | |
669 return FALSE; | |
670 } | |
671 | |
672 DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); | |
673 return TRUE; | |
608 } | 674 } |
609 | 675 |
610 gboolean | 676 gboolean |
611 deliver_finish_list(GList * msgout_list) | 677 deliver_finish_list(GList * msgout_list) |
612 { | 678 { |
613 gboolean ok = TRUE; | 679 gboolean ok = TRUE; |
614 GList *msgout_node; | 680 GList *msgout_node; |
615 foreach(msgout_list, msgout_node) { | 681 foreach(msgout_list, msgout_node) { |
616 msg_out *msgout = (msg_out *) (msgout_node->data); | 682 msg_out *msgout = (msg_out *) (msgout_node->data); |
617 if (!deliver_finish(msgout)) | 683 if (!deliver_finish(msgout)) { |
618 ok = FALSE; | 684 ok = FALSE; |
685 } | |
619 } | 686 } |
620 return ok; | 687 return ok; |
621 } | 688 } |
622 | 689 |
623 gboolean | 690 gboolean |
624 deliver_msgout_list_online(GList * msgout_list) | 691 deliver_msgout_list_online(GList * msgout_list) |
625 { | 692 { |
626 GList *rf_list = NULL; | 693 GList *rf_list = NULL; |
627 gchar *connect_name = detect_online(); | 694 gchar *connect_name = NULL; |
628 gboolean ok = FALSE; | 695 gboolean ok = FALSE; |
629 | 696 |
630 if (connect_name != NULL) { | 697 connect_name = detect_online(); |
631 logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); | 698 if (!connect_name) { |
632 /* we are online! */ | 699 return FALSE; |
633 rf_list = (GList *) table_find(conf.connect_routes, connect_name); | 700 } |
634 if (rf_list != NULL) { | 701 |
635 GList *route_list = read_route_list(rf_list, FALSE); | 702 /* we are online! */ |
636 if (route_list) { | 703 logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); |
637 GList *route_node; | 704 |
638 foreach(route_list, route_node) { | 705 rf_list = (GList *) table_find(conf.connect_routes, connect_name); |
639 connect_route *route = (connect_route *) (route_node->data); | 706 if (!rf_list) { |
640 ok = deliver_route_msg_list(route, msgout_list); | 707 logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); |
641 } | 708 return FALSE; |
642 destroy_route_list(route_list); | 709 } |
643 } else | 710 |
644 logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); | 711 GList *route_list = read_route_list(rf_list, FALSE); |
645 } else { | 712 if (!route_list) { |
646 logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); | 713 logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); |
647 } | 714 return FALSE; |
648 } | 715 } |
716 | |
717 GList *route_node; | |
718 foreach(route_list, route_node) { | |
719 connect_route *route = (connect_route *) (route_node->data); | |
720 /* TODO: ok gets overwritten */ | |
721 ok = deliver_route_msg_list(route, msgout_list); | |
722 } | |
723 destroy_route_list(route_list); | |
649 return ok; | 724 return ok; |
650 } | 725 } |
651 | 726 |
652 gboolean | 727 gboolean |
653 deliver_msg_list(GList * msg_list, guint flags) | 728 deliver_msg_list(GList * msg_list, guint flags) |
654 { | 729 { |
655 GList *msgout_list = create_msg_out_list(msg_list); | 730 GList *msgout_list = create_msg_out_list(msg_list); |
656 GList *local_msgout_list = NULL, *localnet_msgout_list = NULL, *other_msgout_list = NULL; | 731 GList *local_msgout_list = NULL; |
732 GList *localnet_msgout_list = NULL; | |
733 GList *other_msgout_list = NULL; | |
657 GList *msgout_node; | 734 GList *msgout_node; |
658 GList *alias_table = NULL; | 735 GList *alias_table = NULL; |
659 gboolean ok = TRUE; | 736 gboolean ok = TRUE; |
660 | 737 |
661 if (conf.alias_file) { | 738 if (conf.alias_file) { |
677 DEBUG(5) debugf("spool_lock(%s)\n", msgout->msg->uid); | 754 DEBUG(5) debugf("spool_lock(%s)\n", msgout->msg->uid); |
678 | 755 |
679 rcpt_list = g_list_copy(msgout->msg->rcpt_list); | 756 rcpt_list = g_list_copy(msgout->msg->rcpt_list); |
680 if (conf.log_user) { | 757 if (conf.log_user) { |
681 address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name); | 758 address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name); |
682 if (addr) | 759 if (addr) { |
683 rcpt_list = g_list_prepend(rcpt_list, addr); | 760 rcpt_list = g_list_prepend(rcpt_list, addr); |
761 } else { | |
762 logwrite(LOG_ALERT, "invalid log_user address `%s', ignoring\n", conf.log_user); | |
763 } | |
684 } | 764 } |
685 if (alias_table) { | 765 if (alias_table) { |
686 GList *aliased_rcpt_list; | 766 GList *aliased_rcpt_list; |
687 aliased_rcpt_list = alias_expand(alias_table, rcpt_list, msgout->msg->non_rcpt_list); | 767 aliased_rcpt_list = alias_expand(alias_table, rcpt_list, msgout->msg->non_rcpt_list); |
688 g_list_free(rcpt_list); | 768 g_list_free(rcpt_list); |
712 other_msgout->rcpt_list = other_rcpt_list; | 792 other_msgout->rcpt_list = other_rcpt_list; |
713 other_msgout_list = g_list_append(other_msgout_list, other_msgout); | 793 other_msgout_list = g_list_append(other_msgout_list, other_msgout); |
714 } | 794 } |
715 } | 795 } |
716 | 796 |
717 if (alias_table) | 797 if (alias_table) { |
718 destroy_table(alias_table); | 798 destroy_table(alias_table); |
799 } | |
719 | 800 |
720 /* actual delivery */ | 801 /* actual delivery */ |
721 | 802 |
722 if (local_msgout_list) { | 803 if (local_msgout_list) { |
723 DEBUG(5) debugf("local_msgout_list\n"); | 804 DEBUG(5) debugf("local_msgout_list\n"); |
724 foreach(local_msgout_list, msgout_node) { | 805 foreach(local_msgout_list, msgout_node) { |
725 msg_out *msgout = (msg_out *) (msgout_node->data); | 806 msg_out *msgout = (msg_out *) (msgout_node->data); |
726 if (!deliver_local(msgout)) | 807 if (!deliver_local(msgout)) { |
727 ok = FALSE; | 808 ok = FALSE; |
809 } | |
728 } | 810 } |
729 destroy_msg_out_list(local_msgout_list); | 811 destroy_msg_out_list(local_msgout_list); |
730 } | 812 } |
731 | 813 |
732 if (localnet_msgout_list) { | 814 if (localnet_msgout_list) { |
733 GList *route_list = NULL; | 815 GList *route_list = NULL; |
734 GList *route_node; | 816 GList *route_node; |
735 | 817 |
736 DEBUG(5) debugf("localnet_msgout_list\n"); | 818 DEBUG(5) debugf("localnet_msgout_list\n"); |
737 if (conf.local_net_routes) | 819 if (conf.local_net_routes) { |
738 route_list = read_route_list(conf.local_net_routes, TRUE); | 820 route_list = read_route_list(conf.local_net_routes, TRUE); |
739 else | 821 } else { |
740 route_list = g_list_append(NULL, create_local_route()); | 822 route_list = g_list_append(NULL, create_local_route()); |
823 } | |
741 | 824 |
742 foreach(route_list, route_node) { | 825 foreach(route_list, route_node) { |
743 connect_route *route = (connect_route *) (route_node->data); | 826 connect_route *route = (connect_route *) (route_node->data); |
744 if (!deliver_route_msg_list(route, localnet_msgout_list)) | 827 if (!deliver_route_msg_list(route, localnet_msgout_list)) { |
745 ok = FALSE; | 828 ok = FALSE; |
829 } | |
746 } | 830 } |
747 destroy_msg_out_list(localnet_msgout_list); | 831 destroy_msg_out_list(localnet_msgout_list); |
748 destroy_route_list(route_list); | 832 destroy_route_list(route_list); |
749 } | 833 } |
750 | 834 |
751 if (other_msgout_list) { | 835 if (other_msgout_list) { |
752 DEBUG(5) debugf("other_msgout_list\n"); | 836 DEBUG(5) debugf("other_msgout_list\n"); |
753 if (!deliver_msgout_list_online(other_msgout_list)) | 837 if (!deliver_msgout_list_online(other_msgout_list)) { |
754 ok = FALSE; | 838 ok = FALSE; |
839 } | |
755 destroy_msg_out_list(other_msgout_list); | 840 destroy_msg_out_list(other_msgout_list); |
756 } | 841 } |
757 | 842 |
758 foreach(msgout_list, msgout_node) { | 843 foreach(msgout_list, msgout_node) { |
759 msg_out *msgout = (msg_out *) (msgout_node->data); | 844 msg_out *msgout = (msg_out *) (msgout_node->data); |