{"record":{"id":"8c838230d1ff502a","repo":"phacility/phabricator","slug":"err-self","errorCode":"err:self","errorMessage":"Ignoring email with '%s' header to avoid loops.","messagePattern":"Ignoring email with '(.+?)' header to avoid loops\\.","errorType":"exception","errorClass":"PhabricatorMetaMTAReceivedMailProcessingException","httpStatus":null,"severity":"info","filePath":"src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php","lineNumber":368,"sourceCode":"      foreach (explode(',', $addresses) as $address) {\n        $raw_addresses[] = $this->getRawEmailAddress($address);\n      }\n    }\n\n    return array_filter($raw_addresses);\n  }\n\n  /**\n   * If Phabricator sent the mail, always drop it immediately. This prevents\n   * loops where, e.g., the public bug address is also a user email address\n   * and creating a bug sends them an email, which loops.\n   */\n  private function dropMailFromPhabricator() {\n    if (!$this->getHeader('x-phabricator-sent-this-message')) {\n      return;\n    }\n\n    throw new PhabricatorMetaMTAReceivedMailProcessingException(\n      MetaMTAReceivedMailStatus::STATUS_FROM_PHABRICATOR,\n      pht(\n        \"Ignoring email with '%s' header to avoid loops.\",\n        'X-Phabricator-Sent-This-Message'));\n  }\n\n  /**\n   * If this mail has the same message ID as some other mail, and isn't the\n   * first mail we we received with that message ID, we drop it as a duplicate.\n   */\n  private function dropMailAlreadyReceived() {\n    $message_id_hash = $this->getMessageIDHash();\n    if (!$message_id_hash) {\n      // No message ID hash, so we can't detect duplicates. This should only\n      // happen with very old messages.\n      return;\n    }\n","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php#L350-L386","documentation":"dropMailFromPhabricator() runs early in received-mail processing and throws STATUS_FROM_PHABRICATOR whenever the inbound message carries the 'X-Phabricator-Sent-This-Message' header. Phabricator stamps every outbound mail with that header, so any inbound copy of it is Phabricator's own output coming back (e.g. via a loop where the public bug address is also a user's account email). Dropping it immediately prevents infinite mail loops; the status is also one of the two for which no error email is sent back.","triggerScenarios":"An email arrives whose headers include X-Phabricator-Sent-This-Message (Phabricator's own stamp). Typical loop: Phabricator notifies user X at an address that aliases back into a Phabricator inbound address; or a mail rule auto-forwards all mail (including Phabricator notifications) to a Phabricator application address; or reply-all where the notification's own sender address loops back in.","commonSituations":"Auto-forwarding rules on shared mailboxes; the install's notification address being subscribed to its own application address; mailing-list gateways that bounce delivered mail back to Phabricator; testing inbound mail by forwarding an outbound notification by hand.","solutions":["Fix the routing rule that forwards Phabricator's own outbound mail back into an inbound Phabricator address — this status means loop protection fired, which is correct behavior.","When testing inbound mail, compose a NEW message to the application address instead of forwarding a Phabricator notification.","Admins: ensure the addresses Phabricator sends from (noreply/reserved) are never also configured as application receive addresses or members of a forwarded group.","Check MetaMTA > Received Mail: STATUS_FROM_PHABRICATOR rows show which address looped; remove that mapping."],"exampleFix":"// before: mail rule forwards everything, including notifications\n// noreply@ -> bugs@phabricator.example\n// notification carries X-Phabricator-Sent-This-Message -> err:self, dropped\n\n// after: exclude Phabricator-sent mail from the forwarding rule\n// if (header X-Phabricator-Sent-This-Message exists) do not forward","handlingStrategy":"try-catch","validationCode":"// If you implement a mail-ingest script, mirror the guard before doing work:\nif ($received_mail->getHeader('x-phabricator-sent-this-message')) {\n  // this is Phabricator's own output coming back: drop, never auto-forward it\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  $received_mail->processIncomingMail($sender);\n} catch (PhabricatorMetaMTAReceivedMailProcessingException $ex) {\n  if ($ex->getStatusCode() === MetaMTAReceivedMailStatus::STATUS_FROM_PHABRICATOR) {\n    return; // loop protection fired: fix routing, do not requeue\n  }\n  throw $ex;\n}","preventionTips":["Exclude Phabricator outbound addresses from all forwarding rules and mailing lists feeding Phabricator inbound.","When testing inbound mail, compose a new message instead of forwarding a notification.","Investigate any STATUS_FROM_PHABRICATOR row immediately — it marks a live routing loop."],"tags":["metamta","email","loop-prevention","headers","inbound-mail"],"backgroundTag":"mail-loop-detected","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}