{"id":13594111,"url":"https://github.com/mailgun/flanker","last_synced_at":"2025-10-08T17:47:29.528Z","repository":{"id":11827364,"uuid":"14381385","full_name":"mailgun/flanker","owner":"mailgun","description":"Python email address and Mime parsing library","archived":false,"fork":false,"pushed_at":"2024-05-03T19:55:11.000Z","size":10279,"stargazers_count":1643,"open_issues_count":75,"forks_count":206,"subscribers_count":86,"default_branch":"master","last_synced_at":"2025-05-12T04:33:35.008Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.mailgun.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mailgun.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-11-14T01:07:11.000Z","updated_at":"2025-04-28T04:38:25.000Z","dependencies_parsed_at":"2024-06-18T12:44:32.286Z","dependency_job_id":null,"html_url":"https://github.com/mailgun/flanker","commit_stats":null,"previous_names":[],"tags_count":107,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailgun%2Fflanker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailgun%2Fflanker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailgun%2Fflanker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailgun%2Fflanker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mailgun","download_url":"https://codeload.github.com/mailgun/flanker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129481,"owners_count":22019628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T16:01:28.782Z","updated_at":"2025-10-08T17:47:29.461Z","avatar_url":"https://github.com/mailgun.png","language":"Python","funding_links":[],"categories":["Python","Email","资源列表","电子邮件","Email [🔝](#readme)","Awesome Python"],"sub_categories":["电子邮件","Email","Parsers and Tools"],"readme":"Flanker - email address and MIME parsing for Python\n===================================================\n\n.. image:: https://travis-ci.org/mailgun/flanker.svg?branch=master\n    :target: https://travis-ci.org/mailgun/flanker\n\n.. image:: https://coveralls.io/repos/github/mailgun/flanker/badge.svg?branch=master\n    :target: https://coveralls.io/github/mailgun/flanker?branch=master\n\nFlanker is an open source parsing library written in Python by the Mailgun Team.\nFlanker currently consists of an address parsing library (`flanker.addresslib`) as\nwell as a MIME parsing library (`flanker.mime`).\n\nDetailed documentation is provided in the `User Manual \u003chttps://github.com/mailgun/flanker/blob/master/docs/User%20Manual.md\u003e`_ as well as the\n`API Reference \u003chttps://github.com/mailgun/flanker/blob/master/docs/API%20Reference.md\u003e`_. A Quickstart Guide is provided below.\n\nPython Versions\n---------------\n\nFlanker is heavily used by `Mailgun \u003cwww.mailgun.com\u003e`_ in production with\nPython 2.7. The current production version is v0.8.5.\n\nSupport for Python 3 was added in v0.9.0 by popular demand from the community.\nWe are not using Flanker with Python 3 in the house. All we know is that tests\npass with Python 3.6, so use at your own risk. Feel free to report Python 3\nspecific issues if you see any.\n\nInstalling\n----------\n\nYou can install flanker via `pip` or clone the repo from GitHub.\n\nYou'll need Python headers files before you start working with flanker, so install them first:\n\n.. code-block:: bash\n\n   # ubuntu \n   sudo apt-get install python-dev\n   # fedora \n   sudo yum install python-devel\n\nIf you are using `pip`, simply type:\n\n.. code-block:: bash\n\n   pip install flanker\n\nIf you are cloning from GitHub, you can type:\n\n.. code-block:: bash\n\n   git clone git@github.com:mailgun/flanker.git\n   cd flanker\n   pip install -e .\n\nAddress Parsing\n---------------\n\nTo parse a single mailbox (display name as well as email address):\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.parse('Foo foo@example.com')\n   Foo \u003cfoo@example.com\u003e\n\nAn invalid address is returned as `None`:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e print address.parse('@example.com')\n   None\n\nTo parse a single email address (no display name):\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.parse('foo@example.com', addr_spec_only=True)\n   foo@example.com\n\nTo parse an address list:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.parse_list(['foo@example.com, bar@example.com, @example.com'])\n   [foo@example.com, bar@example.com]\n\nTo parse an address list as well as return a tuple containing the parsed \naddresses and the unparsable portions\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.parse_list(['foo@example.com, bar@example.com, @example.com'], as_tuple=True)\n   [foo@example.com, bar@example.com], ['@example.com']\n\nTo parse an address list in strict mode:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.parse_list(['foo@example.com, bar@example.com, @example.com'], strict=True)\n   [foo@example.com, bar@example.com]\n\nTo validate an email address (parse as well as DNS, MX existence, and ESP grammar checks):\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.validate_address('foo@mailgun.com')\n   foo@mailgun.com\n\nTo validate an address list:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker.addresslib import address\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e address.validate_list(['foo@mailgun.com, bar@mailgun.com, @mailgun.com'], as_tuple=True)\n   ([foo@mailgun.com, bar@mailgun.com], ['@mailgun.com'])\n\nMIME Parsing\n------------\n\nFor the following examples, `message_string` will be set to the following MIME message:\n\n::\n\n   MIME-Version: 1.0\n   Content-Type: multipart/alternative; boundary=001a11c1d71697c7f004e6856996\n   From: Bob \u003cbob@example.com\u003e\n   To: Alice \u003calice@example.com\u003e\n   Subject: hello, world\n   Date: Mon, 16 Sep 2013 12:43:03 -0700\n   \n   --001a11c1d71697c7f004e6856996\n   Content-Type: text/plain; charset=us-ascii\n   \n   Hello, *Alice*\n   \n   --001a11c1d71697c7f004e6856996\n   Content-Type: text/html; charset=us-ascii\n   \n   \u003cp\u003eHello, \u003cb\u003eAlice\u003c/b\u003e\u003c/p\u003e\n   \n   --001a11c1d71697c7f004e6856996--\n   \nTo parse a MIME message:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker import mime\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e msg = mime.from_string(message_string)\n\nMIME message headers (unicode multi-value dictionary with headers):\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker import mime\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e msg = mime.from_string(message_string)\n   \u003e\u003e\u003e msg.headers.items()\n   [('Mime-Version', '1.0'),\n    ('Content-Type',\n     ('multipart/alternative', {'boundary': u'001a11c1d71697c7f004e6856996'})),\n    ('From', 'Bob \u003cbob@example.com\u003e'),\n    ('To', 'Alice \u003calice@example.com\u003e'),\n    ('Subject', 'hello, world'),\n    ('Date', 'Mon, 16 Sep 2013 12:43:03 -0700')]\n\nUseful content_type member with predicates:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker import mime\n   \u003e\u003e\u003e msg = mime.from_string(message_string)\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e msg.content_type.is_multipart()\n   True\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e msg.content_type.is_singlepart()\n   False\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e msg.content_type.is_message_container()\n   False \n\nDecoded body of a message:\n\n.. code-block:: py\n\n   \u003e\u003e\u003e from flanker import mime\n   \u003e\u003e\u003e msg = mime.from_string(message_string)\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e # None because message is multipart\n   \u003e\u003e\u003e print msg.body\n   None\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e for part in msg.parts:\n          print 'Content-Type: {} Body: {}'.format(part, part.body)\n\n   Content-Type: (text/plain) Body: Hello, *Alice*\n   Content-Type: (text/html) Body: \u003cp\u003eHello, \u003cb\u003eAlice\u003c/b\u003e\u003c/p\u003e\n\n   \u003e\u003e\u003e # None because no enclosed messages exist\n   \u003e\u003e\u003e print msg.enclosed\n   None\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmailgun%2Fflanker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmailgun%2Fflanker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmailgun%2Fflanker/lists"}