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