|
37 | 37 | from Mailman.Queue.Runner import Runner |
38 | 38 | from Mailman.Queue.Switchboard import Switchboard |
39 | 39 | from Mailman.Queue.BounceRunner import BounceMixin |
| 40 | +from Mailman.List import MailList |
40 | 41 |
|
41 | 42 | # This controls how often _doperiodic() will try to deal with deferred |
42 | 43 | # permanent failures. It is a count of calls to _doperiodic() |
@@ -222,73 +223,90 @@ def _dispose(self, mlist, msg, msgdata): |
222 | 223 | msgid = msg.get('message-id', 'n/a') |
223 | 224 | filebase = msgdata.get('_filebase', 'unknown') |
224 | 225 |
|
225 | | - mailman_log('debug', 'OutgoingRunner._dispose: Starting to process outgoing message %s (file: %s) for list %s', |
226 | | - msgid, filebase, mlist.internal_name()) |
| 226 | + # Ensure we have a MailList object |
| 227 | + if isinstance(mlist, str): |
| 228 | + try: |
| 229 | + mlist = MailList.MailList(mlist, lock=0) |
| 230 | + should_unlock = True |
| 231 | + except Errors.MMUnknownListError: |
| 232 | + mailman_log('error', 'OutgoingRunner: Unknown list %s', mlist) |
| 233 | + self._shunt.enqueue(msg, msgdata) |
| 234 | + return True |
| 235 | + else: |
| 236 | + should_unlock = False |
227 | 237 |
|
228 | | - # Check retry delay and duplicate processing |
229 | | - if not self._check_retry_delay(msgid, filebase): |
230 | | - mailman_log('debug', 'OutgoingRunner._dispose: Message %s failed retry delay check, skipping', msgid) |
231 | | - return False |
232 | | - |
233 | | - # Make sure we have the most up-to-date state |
234 | 238 | try: |
235 | | - mlist.Load() |
236 | | - mailman_log('debug', 'OutgoingRunner._dispose: Successfully loaded list %s', mlist.internal_name()) |
237 | | - except Errors.MMCorruptListDatabaseError as e: |
238 | | - mailman_log('error', 'OutgoingRunner._dispose: Failed to load list %s: %s\nTraceback:\n%s', |
239 | | - mlist.internal_name(), str(e), traceback.format_exc()) |
240 | | - self._unmark_message_processed(msgid) |
241 | | - return False |
242 | | - except Exception as e: |
243 | | - mailman_log('error', 'OutgoingRunner._dispose: Unexpected error loading list %s: %s\nTraceback:\n%s', |
244 | | - mlist.internal_name(), str(e), traceback.format_exc()) |
245 | | - self._unmark_message_processed(msgid) |
246 | | - return False |
| 239 | + mailman_log('debug', 'OutgoingRunner._dispose: Starting to process outgoing message %s (file: %s) for list %s', |
| 240 | + msgid, filebase, mlist.internal_name()) |
| 241 | + |
| 242 | + # Check retry delay and duplicate processing |
| 243 | + if not self._check_retry_delay(msgid, filebase): |
| 244 | + mailman_log('debug', 'OutgoingRunner._dispose: Message %s failed retry delay check, skipping', msgid) |
| 245 | + return False |
247 | 246 |
|
248 | | - # Validate message type first |
249 | | - msg, success = self._validate_message(msg, msgdata) |
250 | | - if not success: |
251 | | - mailman_log('error', 'OutgoingRunner._dispose: Message validation failed for message %s', msgid) |
252 | | - self._unmark_message_processed(msgid) |
253 | | - return False |
| 247 | + # Make sure we have the most up-to-date state |
| 248 | + try: |
| 249 | + mlist.Load() |
| 250 | + mailman_log('debug', 'OutgoingRunner._dispose: Successfully loaded list %s', mlist.internal_name()) |
| 251 | + except Errors.MMCorruptListDatabaseError as e: |
| 252 | + mailman_log('error', 'OutgoingRunner._dispose: Failed to load list %s: %s\nTraceback:\n%s', |
| 253 | + mlist.internal_name(), str(e), traceback.format_exc()) |
| 254 | + self._unmark_message_processed(msgid) |
| 255 | + return False |
| 256 | + except Exception as e: |
| 257 | + mailman_log('error', 'OutgoingRunner._dispose: Unexpected error loading list %s: %s\nTraceback:\n%s', |
| 258 | + mlist.internal_name(), str(e), traceback.format_exc()) |
| 259 | + self._unmark_message_processed(msgid) |
| 260 | + return False |
254 | 261 |
|
255 | | - # Validate message headers |
256 | | - if not msg.get('message-id'): |
257 | | - mailman_log('error', 'OutgoingRunner._dispose: Message missing Message-ID header') |
258 | | - self._unmark_message_processed(msgid) |
259 | | - return False |
| 262 | + # Validate message type first |
| 263 | + msg, success = self._validate_message(msg, msgdata) |
| 264 | + if not success: |
| 265 | + mailman_log('error', 'OutgoingRunner._dispose: Message validation failed for message %s', msgid) |
| 266 | + self._unmark_message_processed(msgid) |
| 267 | + return False |
260 | 268 |
|
261 | | - # Process the outgoing message |
262 | | - try: |
263 | | - mailman_log('debug', 'OutgoingRunner._dispose: Processing outgoing message %s', msgid) |
264 | | - |
265 | | - # Get message type and recipient |
266 | | - msgtype = msgdata.get('_msgtype', 'unknown') |
267 | | - recipient = msgdata.get('recipient', 'unknown') |
268 | | - |
269 | | - mailman_log('debug', 'OutgoingRunner._dispose: Message %s is type %s for recipient %s', |
270 | | - msgid, msgtype, recipient) |
271 | | - |
272 | | - # Process based on message type |
273 | | - if msgtype == 'bounce': |
274 | | - success = self._process_bounce(mlist, msg, msgdata) |
275 | | - elif msgtype == 'admin': |
276 | | - success = self._process_admin(mlist, msg, msgdata) |
277 | | - else: |
278 | | - success = self._process_regular(mlist, msg, msgdata) |
279 | | - |
280 | | - if success: |
281 | | - mailman_log('debug', 'OutgoingRunner._dispose: Successfully processed outgoing message %s', msgid) |
282 | | - return True |
283 | | - else: |
284 | | - mailman_log('error', 'OutgoingRunner._dispose: Failed to process outgoing message %s', msgid) |
| 269 | + # Validate message headers |
| 270 | + if not msg.get('message-id'): |
| 271 | + mailman_log('error', 'OutgoingRunner._dispose: Message missing Message-ID header') |
| 272 | + self._unmark_message_processed(msgid) |
285 | 273 | return False |
286 | 274 |
|
287 | | - except Exception as e: |
288 | | - mailman_log('error', 'OutgoingRunner._dispose: Error processing outgoing message %s: %s\nTraceback:\n%s', |
289 | | - msgid, str(e), traceback.format_exc()) |
290 | | - self._unmark_message_processed(msgid) |
291 | | - return False |
| 275 | + # Process the outgoing message |
| 276 | + try: |
| 277 | + mailman_log('debug', 'OutgoingRunner._dispose: Processing outgoing message %s', msgid) |
| 278 | + |
| 279 | + # Get message type and recipient |
| 280 | + msgtype = msgdata.get('_msgtype', 'unknown') |
| 281 | + recipient = msgdata.get('recipient', 'unknown') |
| 282 | + |
| 283 | + mailman_log('debug', 'OutgoingRunner._dispose: Message %s is type %s for recipient %s', |
| 284 | + msgid, msgtype, recipient) |
| 285 | + |
| 286 | + # Process based on message type |
| 287 | + if msgtype == 'bounce': |
| 288 | + success = self._process_bounce(mlist, msg, msgdata) |
| 289 | + elif msgtype == 'admin': |
| 290 | + success = self._process_admin(mlist, msg, msgdata) |
| 291 | + else: |
| 292 | + success = self._process_regular(mlist, msg, msgdata) |
| 293 | + |
| 294 | + if success: |
| 295 | + mailman_log('debug', 'OutgoingRunner._dispose: Successfully processed outgoing message %s', msgid) |
| 296 | + return True |
| 297 | + else: |
| 298 | + mailman_log('error', 'OutgoingRunner._dispose: Failed to process outgoing message %s', msgid) |
| 299 | + return False |
| 300 | + |
| 301 | + except Exception as e: |
| 302 | + mailman_log('error', 'OutgoingRunner._dispose: Error processing outgoing message %s: %s\nTraceback:\n%s', |
| 303 | + msgid, str(e), traceback.format_exc()) |
| 304 | + self._unmark_message_processed(msgid) |
| 305 | + return False |
| 306 | + |
| 307 | + finally: |
| 308 | + if should_unlock: |
| 309 | + mlist.Unlock() |
292 | 310 |
|
293 | 311 | def _process_bounce(self, mlist, msg, msgdata): |
294 | 312 | """Process a bounce message.""" |
|
0 commit comments