[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.{config, src}]\nindent_style = space\n\n[*.md]\nindent_style = space\ntrim_trailing_whitespace = false\n\n[*.yml]\nindent_style = space\nindent_size = 2\n\n[*.eml]\nend_of_line = crlf\ninsert_final_newline = false\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "# git blame ignore list.\n#\n# This file contains a list of git hashes to be ignored by git blame. These\n# revisions are considered \"unimportant\" in that they are unlikely to be what\n# you are interested in when blaming.\n#\n#     git blame --ignore-revs-file .git-blame-ignore-revs\n# or\n#     git config blame.ignoreRevsFile .git-blame-ignore-revs\n\n# Code formatter applied: `rebar3 fmt`\n3967bcbd349b2bf0c390f68c68bd1d79eb5ad1fc\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non: [push, pull_request]\n\njobs:\n\n  ci:\n    name: Test on OTP ${{ matrix.otp }} / Profile ${{ matrix.profile }}\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        os: [ubuntu-22.04]\n        otp: [\"25\", \"24\"]\n        rebar3: [\"3.18.0\"]\n        profile: [test, ranch_v2]\n\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: erlef/setup-beam@v1\n        with:\n          otp-version: ${{ matrix.otp }}\n          rebar3-version: ${{ matrix.rebar3 }}\n\n      - name: Cache Hex packages\n        uses: actions/cache@v3\n        with:\n          path: ~/.cache/rebar3/hex/hexpm/packages\n          key: ${{ runner.os }}-hex-${{ hashFiles('**/rebar.lock') }}\n          restore-keys: ${{ runner.os }}-hex-\n\n      - name: Cache Dialyzer PLTs\n        uses: actions/cache@v3\n        with:\n          path: |\n            ~/.cache/rebar3/rebar3_*_plt\n            _build/dialyzer/rebar3_*_plt\n          key: ${{ runner.os }}-${{ matrix.otp }}-dialyzer-${{ hashFiles('**/rebar.config') }}\n          restore-keys: ${{ runner.os }}-${{ matrix.otp }}-dialyzer-\n\n      - name: Xref\n        run: make xref\n\n      - name: Format\n        run: rebar3 fmt --check\n\n      - name: Test\n        run: make test REBAR_PROFILE=${{ matrix.profile }}\n\n      - name: Proper\n        run: make proper REBAR_PROFILE=${{ matrix.profile }}\n\n      - name: Cover\n        run: make cover REBAR_PROFILE=${{ matrix.profile }}\n\n      - name: Dialyzer\n        run: make dialyze\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n\n  docs:\n    name: Generate docs on OTP ${{ matrix.otp }}\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        os: [ubuntu-latest]\n        otp: [\"25\"] # https://www.erlang.org/downloads\n        rebar3: [\"3.18.0\"] # https://www.rebar3.org\n\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: erlef/setup-beam@v1\n        with:\n          otp-version: ${{ matrix.otp }}\n          rebar3-version: ${{ matrix.rebar3 }}\n\n      - name: Cache Hex packages\n        uses: actions/cache@v3\n        with:\n          path: ~/.cache/rebar3/hex/hexpm/packages\n          key: ${{ runner.os }}-hex-${{ hashFiles('**/rebar.lock') }}\n          restore-keys: ${{ runner.os }}-hex-\n\n      - name: Generate docs by ExDoc\n        run: rebar3 ex_doc\n"
  },
  {
    "path": ".gitignore",
    "content": "*.swp\n*.beam\nerl_crash.dump\ncoverage/*\ndoc/\n.DS_Store\nbuild\n*.xcodeproj\n.eunit/\nebin/gen_smtp.app\nsrc/smtp_rfc822_parse.erl\nsrc/smtp_rfc5322_scan.erl\nsrc/smtp_rfc5322_parse.erl\ndeps/\n_build\n.rebar\ncompile_commands.json\nrebar3.crashdump\n"
  },
  {
    "path": "Emakefile",
    "content": "{\"src/*\", [debug_info, {outdir, \"ebin\"},\n {i, \"include\"}]}.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright 2009-2011 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice,\n     this list of conditions and the following disclaimer.\n  2. Redistributions in binary form must reproduce the above copyright\n     notice, this list of conditions and the following disclaimer in the\n     documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE PROJECT ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\nEVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n"
  },
  {
    "path": "Makefile",
    "content": "REBAR_PROFILE = test\nMINIMAL_COVERAGE = 75\n\ncompile:\n\t@rebar3 compile\n\nclean:\n\t@rebar3 clean -a\n\ntest:\n\tERL_AFLAGS=\"-s ssl\"\n\trebar3 as $(REBAR_PROFILE) eunit -c\n\nproper:\n\trebar3 as $(REBAR_PROFILE) proper -c\n\ncover:\n\trebar3 as $(REBAR_PROFILE) cover --verbose --min_coverage $(MINIMAL_COVERAGE)\n\ndialyze:\n\trebar3 as dialyzer dialyzer\n\nxref:\n\trebar3 as test xref\n\nformat:\n\trebar3 fmt\n\ndocs:\n\trebar3 ex_doc\n\n.PHONY: compile clean test dialyze\n"
  },
  {
    "path": "README.md",
    "content": "# gen_smtp\n\n[![Hex pm](http://img.shields.io/hexpm/v/gen_smtp.svg?style=flat)](https://hex.pm/packages/gen_smtp)\n[![CI](https://github.com/gen-smtp/gen_smtp/actions/workflows/ci.yml/badge.svg)](https://github.com/gen-smtp/gen_smtp/actions/workflows/ci.yml)\n[![Docs](https://github.com/gen-smtp/gen_smtp/actions/workflows/docs.yml/badge.svg)](https://github.com/gen-smtp/gen_smtp/actions/workflows/docs.yml)\n\nThe Erlang SMTP client and server library.\n\n## Mission\n\nProvide a generic Erlang SMTP server framework that can be extended via\ncallback modules in the OTP style. A pure Erlang SMTP client is also included.\nThe goal is to make it easy to send and receive email in Erlang without the\nhassle of POP/IMAP. This is *not* a complete mailserver - although it includes\nmost of the parts you'd need to build one.\n\nThe SMTP server/client supports PLAIN, LOGIN, CRAM-MD5 authentication as well\nas STARTTLS and SSL (port 465).\n\nAlso included is a MIME encoder/decoder, sorta according to RFC204{5,6,7}.\n\nIPv6 is also supported (at least serverside).\n\nSMTP server uses ranch as socket acceptor. It can use Ranch 1.8+, as well as 2.x.\n\nI (Vagabond) have had a simple gen_smtp based SMTP server receiving and parsing\ncopies of all my email for several months and its been able to handle over 100\nthousand emails without leaking any RAM or crashing the erlang virtual machine.\n\n## Current Participants\n\n+ Andrew Thompson (andrew AT hijacked.us)\n+ Jack Danger Canty (code AT jackcanty.com)\n+ Micah Warren (micahw AT lordnull.com)\n+ Arjan Scherpenisse (arjan AT botsquad.com)\n+ Marc Worrell (marc AT worrell.nl)\n\n## Who is using it?\n\n+ gen_smtp is used to provide the email functionality of [OpenACD](https://github.com/OpenACD/OpenACD)\n+ gen_smtp is used as both the SMTP server and SMTP client for [Zotonic](http://zotonic.com)\n+ [Chicago Boss](http://www.chicagoboss.org/) uses gen_smtp for its mail API.\n+ [Gmailbox](https://www.gmailbox.org) uses gen_smtp to provide a free email forwarding service.\n+ [JOSHMARTIN GmbH](https://joshmartin.ch/) uses gen_smtp to send emails in [Hygeia](https://covid19-tracing.ch/) to send emails for contact tracing of SARS-CoV-2.\n+ [hookup.email](https://hookup.email) uses gen_smtp to receive and parse emails the service forwards to webhooks, APIs, or any other HTTP application.\n+ many libraries [depend on gen_smtp](https://hex.pm/packages/gen_smtp) according to hex.pm\n\nIf you'd like to share your usage of gen_smtp, please submit a PR to this `README.md`.\n\n# Usage\n\n## Client Example\n\nHere's an example usage of the client:\n\n```erlang\ngen_smtp_client:send({\"whatever@test.com\", [\"andrew@hijacked.us\"],\n \"Subject: testing\\r\\nFrom: Andrew Thompson <andrew@hijacked.us>\\r\\nTo: Some Dude <foo@bar.com>\\r\\n\\r\\nThis is the email body\"},\n  [{relay, \"smtp.gmail.com\"}, {username, \"me@gmail.com\"}, {password, \"mypassword\"}]).\n```\n\nThe From and To addresses will be wrapped in `<>` if they aren't already,\nTLS will be auto-negotiated if available (unless you pass `{tls, never}`) and\nauthentication will by attempted by default since a username/password were\nspecified (`{auth, never}` overrides this).\n\nIf you want to mandate tls or auth, you can pass `{tls, always}` or `{auth,\nalways}` as one of the options. You can specify an alternate port with `{port,\n2525}` (default is 25) or you can indicate that the server is listening for SSL\nconnections using `{ssl, true}` (port defaults to 465 with this option).\n\n### Options\n\n    send(Email, Options)\n    send(Email, Options, Callback)\n    send_blocking(Email, Options)\n\nThe `send` method variants `send/2, send/3, send_blocking/2` take an `Options` argument.\n`Options` must be a proplist with the following valid values:\n\n  * **relay** the smtp relay, e.g. `\"smtp.gmail.com\"`\n  * **username** the username of the smtp relay e.g. `\"me@gmail.com\"`\n  * **password** the password of the smtp relay e.g. `\"mypassword\"`\n  * **auth** whether the smtp server needs authentication. Valid values are `if_available`, `always`, and `never`. Defaults to `if_available`. If your smtp relay requires authentication set it to `always`\n  * **ssl** whether to connect on 465 in ssl mode. Defaults to `false`\n  * **sockopts** used for the initial plain or SSL/TLS TCP connection. More info at Erlang documentation [gen_tcp](https://www.erlang.org/doc/man/gen_tcp.html) and [ssl](https://www.erlang.org/doc/man/ssl.html). Defaults to `[binary, {packet, line}, {keepalive, true}, {active, false}]`.\n  * **tls** valid values are `always`, `never`, `if_available`. Most modern smtp relays use tls, so set this to `always`. Defaults to `if_available`\n  * **tls_options** used for `STARTTLS` upgrades in `ssl:connect`, More info at [Erlang documentation - ssl](https://www.erlang.org/doc/man/ssl.html). Defaults to `[{versions , ['tlsv1', 'tlsv1.1', 'tlsv1.2']}]`. This is merged with options listed at: [smtp_socket.erl#L50 - SSL_CONNECT_OPTIONS](https://github.com/gen-smtp/gen_smtp/blob/master/src/smtp_socket.erl#L50) .\n  * **hostname** the hostname to be used by the smtp relay. Defaults to: `smtp_util:guess_FQDN()`. The hostname on your computer might not be correct, so set this to a valid value.\n  * **retries** how many retries per smtp host on temporary failure. Defaults to 1, which means it will retry once if there is a failure.\n  * **protocol** valid values are `smtp`, `lmtp`. Default is `smtp`\n\n\n### DKIM signing of outgoing emails\n\nYou may wish to configure DKIM signing [RFC6376](https://datatracker.ietf.org/doc/html/rfc5672) or [RFC8463](https://datatracker.ietf.org/doc/html/rfc8463) (Ed25519) of outgoing emails\nfor better security. To do that you need public and private keys, which can be generated by\nfollowing commands:\n\n```bash\n# RSA\nopenssl genrsa -out private-key.pem 1024\nopenssl rsa -in private-key.pem -out public-key.pem -pubout\n\n# Ed25519 - Erlang/OTP 24.1+ only!\nopenssl genpkey -algorithm ed25519 -out private-key.pem\nopenssl pkey -in private-key.pem -pubout -out public-key.pem\n# DKIM DNS record p value for Ed25519 must only contain Base64 encoded public key, without ASN.1\nopenssl asn1parse -in public-key.pem -offset 12 -noout -out /dev/stdout | openssl base64\n```\n\nTo send DKIM-signed email:\n\n```erlang\n{ok, PrivKey} = file:read_file(\"private-key.pem\"),\nDKIMOptions = [\n    {s, <<\"foo.bar\">>},\n    {d, <<\"example.com\">>},\n    {private_key, {pem_plain, PrivKey}}]}\n    %{private_key, {pem_encrypted, EncryptedPrivKey, \"password\"}}\n],\nSignedMailBody = \\\n mimemail:encode({<<\"text\">>, <<\"plain\">>,\n                  [{<<\"Subject\">>, <<\"DKIM testing\">>},\n                   {<<\"From\">>, <<\"Andrew Thompson <andrew@hijacked.us>\">>},\n                   {<<\"To\">>, <<\"Some Dude <foo@bar.com>\">>}],\n                  #{},\n                  <<\"This is the email body\">>},\n                  [{dkim, DKIMOptions}]),\ngen_smtp_client:send({\"whatever@example.com\", [\"andrew@hijacked.us\"], SignedMailBody}, []).\n```\n\nFor using Ed25519 you need to set the option `{a, 'ed25519-sha256'}`.\n\nDon't forget to put your public key to `foo.bar._domainkey.example.com` TXT DNS record as something like\n\nRSA:\n```\nv=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBA......\n```\n\nEd25519:\n```\nv=DKIM1; g=*; k=ed25519; p=MIGfMA0GCSqGSIb3DQEBA......\n```\n\nSee RFC6376 for more details.\n\n## Server Example\n\n`gen_smtp` ships with a simple callback server example, `smtp_server_example`. To start the SMTP server with this as the callback module, issue the following command:\n\n```erlang\ngen_smtp_server:start(smtp_server_example).\ngen_smtp_server starting at nonode@nohost\nlistening on {0,0,0,0}:2525 via tcp\n{ok,<0.33.0>}\n```\n\nBy default it listens on 0.0.0.0 port 2525. You can telnet to it and test it:\n\n```\n^andrew@orz-dashes:: telnet localhost 2525                                                      [~]\nTrying 127.0.0.1...\nConnected to localhost.\nEscape character is '^]'.\n220 localhost ESMTP smtp_server_example\nEHLO example.com\n250-orz-dashes\n250-SIZE 10485670\n250-8BITMIME\n250-PIPELINING\n250 WTF\nMAIL FROM: andrew@hijacked.us\n250 sender Ok\nRCPT TO: andrew@hijacked.us\n250 recipient Ok\nDATA\n354 enter mail, end with line containing only '.'\nGood evening gentlemen, all your base are belong to us.\n.\n250 queued as d98ae19ee87f0741ac9ba90d7046f0c5\nQUIT\n221 Bye\nConnection closed by foreign host.\n```\n\nYou can configure the server in general, each SMTP session, and the callback module, for example:\n\n```erlang\ngen_smtp_server:start(\n    smtp_server_example,\n    [{sessionoptions, [{allow_bare_newlines, fix},\n                       {callbackoptions, [{parse, true}]}]}]).\n```\n\nThis configures the session to fix bare newlines (other options are `strip`, `ignore` and `false`: `false` rejects emails with bare newlines, `ignore` passes them through unmodified and `strip` removes them) and tells the callback module to run the MIME decoder on the email once its been received. The example callback module also supports the following options: `relay` - whether to relay email on, `auth` - whether to do SMTP authentication and `parse` - whether to invoke the MIME parser. The example callback module is included mainly as an example and are not intended for serious usage. You could easily create your own callback options.\nIn general, following options can be specified `gen_smtp_server:options()`:\n\n* `{domain, string()}` - is used as server hostname (it's placed to SMTP server banner and HELO/EHLO response), default - guess from machine hostname\n* `{address, inet:ip4_address()}` - IP address to listen on, default `{0, 0, 0, 0}`\n* `{port, inet:port_number()}` - port to listen on, default `2525`\n* `{family, inet | inet6}` - IP address type (IPv4/IPv6), default `inet`\n* `{protocol, tcp | ssl}` - listen in tcp or ssl mode, default `tcp`\n* `{ranch_opts, ranch:opts()}` - format depends on ranch version. Consult Ranch documentation.\n* `{sessionoptions, gen_smtp_server_session:options()}` - see below\n\nSession options are:\n\n* `{allow_bare_newlines, false | ignore | fix | strip}` - see above\n* `{hostname, inet:hostname()}` - which hostname server should send in response\n  to `HELO` / `EHLO` commands. Default: `inet:gethostname()`.\n* `{tls_options, [ssl:server_option()]}` - options to pass to `ssl:handshake/3`\n  when `STARTTLS` command is sent by the client. Only needed if `STARTTLS` extension\n  is enabled\n* `{protocol, smtp | lmtp}` - when `lmtp` is passed, the control flow of the\n  [Local Mail Transfer Protocol](https://tools.ietf.org/html/rfc2033) is applied.\n  LMTP is derived from SMTP with just a few variations and is used by standard\n  [Mail Transfer Agents (MTA)](https://en.wikipedia.org/wiki/Message_transfer_agent), like Postfix, Exim and OpenSMTPD to\n  send incoming email to local mail-handling applications that usually don't have a delivery queue.\n  The default value of this option is `smtp`.\n* `{callbackoptions, any()}` - value will be passed as 4th argument to callback module's `init/4`\n\nYou can connect and test this using the `gen_smtp_client` via something like:\n\n```erlang\ngen_smtp_client:send(\n    {\"whatever@test.com\", [\"andrew@hijacked.us\"], \"Subject: testing\\r\\nFrom: Andrew Thompson \\r\\nTo: Some Dude \\r\\n\\r\\nThis is the email body\"},\n    [{relay, \"localhost\"}, {port, 2525}]).\n```\n\nIf you want to listen on IPv6, you can use the `{family, inet6}` and `{address, {0, 0, 0, 0, 0, 0, 0, 0}}` options to enable listening on IPv6.\n\nPlease notice that when using the LMTP protocol, the `handle_EHLO` callback will be used\nto handle the `LHLO` command as defined in [RFC2033](https://tools.ietf.org/html/rfc2033),\ndue to their similarities. Although not used, the implementation of `handle_HELO` is still\nmandatory for the general `gen_smtp_server_session` behaviour (you can simply\nreturn a 500 error, e.g. `{error, \"500 LMTP server, not SMTP\"}`).\n\n## Dependency on iconv\n\ngen_smtp relies on iconv for text encoding and decoding when parsing is activated.\n\nTo use gen_smtp, a `eiconv` module must be loaded, with a `convert/3` function.\n\nYou can use [Zotonic/eiconv](https://github.com/zotonic/eiconv), which is used\nfor tests on the project.\n\nFor that, you can add the following line to your `rebar.config` file:\n\n```\n{deps, [\n  {eiconv, \"1.0.0\"}\n]}.\n```\n"
  },
  {
    "path": "VERSION",
    "content": "1.3.0"
  },
  {
    "path": "rebar.config",
    "content": "%% -*- mode: erlang; -*-\n{minimum_otp_vsn, \"21\"}.\n\n{erl_opts, [\n    fail_on_warning,\n    debug_info,\n    warn_unused_vars,\n    warn_unused_import,\n    warn_exported_vars\n]}.\n\n{xref_checks, [\n    undefined_function_calls,\n    undefined_functions,\n    locals_not_used,\n    %% exports_not_used,\n    deprecated_function_calls,\n    deprecated_functions\n]}.\n\n{project_plugins, [\n    erlfmt,\n    rebar3_ex_doc,\n    rebar3_proper\n]}.\n\n{erlfmt, [\n    write,\n    {print_width, 120},\n    {files, [\n        \"{src,include,test}/*.{hrl,erl}\",\n        \"src/*.app.src\",\n        \"rebar.config\"\n    ]},\n    {exclude_files, [\n        \"src/smtp_rfc5322_parse.erl\",\n        \"src/smtp_rfc5322_scan.erl\",\n        \"src/smtp_rfc822_parse.erl\"\n    ]}\n]}.\n\n{xref_ignores, [\n    {smtp_rfc822_parse, return_error, 2}\n]}.\n\n{deps, [\n    {ranch, \">= 1.8.0\"}\n]}.\n\n{profiles, [\n    {dialyzer, [\n        {deps, [\n            {eiconv, \"1.0.0\"}\n        ]},\n        {dialyzer, [\n            {plt_extra_apps, [\n                eiconv,\n                ssl\n            ]},\n            {warnings, [\n                error_handling,\n                unknown\n            ]}\n        ]}\n    ]},\n    {ranch_v2, [{deps, [{ranch, \"2.1.0\"}]}]},\n    {test, [\n        {cover_enabled, true},\n        {cover_print_enabled, true},\n        {deps, [\n            {eiconv, \"1.0.0\"},\n            {proper, \"1.3.0\"}\n        ]}\n    ]}\n]}.\n\n{ex_doc, [\n    {source_url, <<\"https://github.com/gen-smtp/gen_smtp\">>},\n    {prefix_ref_vsn_with_v, false},\n    {extras, [\n        {'README.md', #{title => \"Overview\"}},\n        {'LICENSE', #{title => \"License\"}}\n    ]},\n    {main, <<\"readme\">>}\n]}.\n\n{hex, [\n    {doc, #{provider => ex_doc}}\n]}.\n"
  },
  {
    "path": "src/binstr.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc Some functions for working with binary strings.\n\n-module(binstr).\n\n-export([\n    strchr/2,\n    strrchr/2,\n    strpos/2,\n    strrpos/2,\n    substr/2,\n    substr/3,\n    split/3,\n    split/2,\n    chomp/1,\n    strip/1,\n    strip/2,\n    strip/3,\n    to_lower/1,\n    to_upper/1,\n    all/2,\n    reverse/1,\n    reverse_str_to_bin/1,\n    join/2\n]).\n\n-spec strchr(Bin :: binary(), C :: char()) -> non_neg_integer().\nstrchr(Bin, C) when is_binary(Bin) ->\n    case binary:match(Bin, <<C>>) of\n        {Index, _Length} ->\n            Index + 1;\n        nomatch ->\n            0\n    end.\n\n-spec strrchr(Bin :: binary(), C :: char()) -> non_neg_integer().\nstrrchr(Bin, C) ->\n    strrchr(Bin, C, byte_size(Bin)).\n\nstrrchr(Bin, C, I) ->\n    case Bin of\n        <<_X:I/binary, C, _Rest/binary>> ->\n            I + 1;\n        _ when I =< 1 ->\n            0;\n        _ ->\n            strrchr(Bin, C, I - 1)\n    end.\n\n-spec strpos(Bin :: binary(), C :: binary() | list()) -> non_neg_integer().\nstrpos(Bin, C) when is_binary(Bin), is_list(C) ->\n    strpos(Bin, list_to_binary(C));\nstrpos(Bin, C) when is_binary(Bin) ->\n    case binary:match(Bin, C) of\n        {Index, _Length} ->\n            Index + 1;\n        nomatch ->\n            0\n    end.\n\n-spec strrpos(Bin :: binary(), C :: binary() | list()) -> non_neg_integer().\nstrrpos(Bin, C) ->\n    strrpos(Bin, C, byte_size(Bin), byte_size(C)).\n\nstrrpos(Bin, C, I, S) ->\n    case Bin of\n        <<_X:I/binary, C:S/binary, _Rest/binary>> ->\n            I + 1;\n        _ when I =< 1 ->\n            0;\n        _ ->\n            strrpos(Bin, C, I - 1, S)\n    end.\n\n-spec substr(Bin :: binary(), Start :: pos_integer() | neg_integer()) -> binary().\nsubstr(<<>>, _) ->\n    <<>>;\nsubstr(Bin, Start) when Start > 0 ->\n    {_, B2} = split_binary(Bin, Start - 1),\n    B2;\nsubstr(Bin, Start) when Start < 0 ->\n    Size = byte_size(Bin),\n    {_, B2} = split_binary(Bin, Size + Start),\n    B2.\n\n-spec substr(Bin :: binary(), Start :: pos_integer() | neg_integer(), Length :: pos_integer()) ->\n    binary().\nsubstr(<<>>, _, _) ->\n    <<>>;\nsubstr(Bin, Start, Length) when Start > 0 ->\n    {_, B2} = split_binary(Bin, Start - 1),\n    {B3, _} = split_binary(B2, Length),\n    B3;\nsubstr(Bin, Start, Length) when Start < 0 ->\n    Size = byte_size(Bin),\n    {_, B2} = split_binary(Bin, Size + Start),\n    {B3, _} = split_binary(B2, Length),\n    B3.\n\n-spec split(Bin :: binary(), Separator :: binary(), SplitCount :: pos_integer()) -> [binary()].\nsplit(Bin, Separator, SplitCount) ->\n    split_(Bin, Separator, SplitCount, []).\n\nsplit_(<<>>, _Separator, _SplitCount, Acc) ->\n    lists:reverse(Acc);\nsplit_(Bin, <<>>, 1, Acc) ->\n    lists:reverse([Bin | Acc]);\nsplit_(Bin, _Separator, 1, Acc) ->\n    lists:reverse([Bin | Acc]);\nsplit_(Bin, <<>>, SplitCount, Acc) ->\n    split_(substr(Bin, 2), <<>>, SplitCount - 1, [substr(Bin, 1, 1) | Acc]);\nsplit_(Bin, Separator, SplitCount, Acc) ->\n    case strpos(Bin, Separator) of\n        0 ->\n            lists:reverse([Bin | Acc]);\n        Index ->\n            Head = substr(Bin, 1, Index - 1),\n            Tailpresplit = substr(Bin, Index + byte_size(Separator)),\n            split_(Tailpresplit, Separator, SplitCount - 1, [Head | Acc])\n    end.\n\n-spec split(Bin :: binary(), Separator :: binary()) -> [binary()].\nsplit(Bin, Separator) ->\n    case binary:split(Bin, Separator, [global]) of\n        Result ->\n            case lists:last(Result) of\n                <<>> ->\n                    lists:sublist(Result, length(Result) - 1);\n                _ ->\n                    Result\n            end\n    end.\n\n-spec chomp(Bin :: binary()) -> binary().\nchomp(Bin) ->\n    L = byte_size(Bin),\n    case [binary:at(Bin, L - 2), binary:at(Bin, L - 1)] of\n        \"\\r\\n\" ->\n            binary:part(Bin, 0, L - 2);\n        [_, X] when X == $\\r; X == $\\n ->\n            binary:part(Bin, 0, L - 1);\n        _ ->\n            Bin\n    end.\n\n-spec strip(Bin :: binary()) -> binary().\nstrip(Bin) ->\n    strip(Bin, both, $\\s).\n\n-spec strip(Bin :: binary(), Dir :: 'left' | 'right' | 'both') -> binary().\nstrip(Bin, Dir) ->\n    strip(Bin, Dir, $\\s).\n\n-spec strip(Bin :: binary(), Dir :: 'left' | 'right' | 'both', C :: non_neg_integer()) -> binary().\nstrip(<<>>, _, _) ->\n    <<>>;\nstrip(Bin, both, C) ->\n    strip(strip(Bin, left, C), right, C);\nstrip(<<C, _Rest/binary>> = Bin, left, C) ->\n    strip(substr(Bin, 2), left, C);\nstrip(Bin, left, _C) ->\n    Bin;\nstrip(Bin, right, C) ->\n    L = byte_size(Bin),\n    case binary:at(Bin, L - 1) of\n        C ->\n            strip(binary:part(Bin, 0, L - 1), right, C);\n        _ ->\n            Bin\n    end.\n\n-spec to_lower(Bin :: binary()) -> binary().\nto_lower(Bin) ->\n    to_lower(Bin, <<>>).\n\nto_lower(<<>>, Acc) ->\n    Acc;\nto_lower(<<H, T/binary>>, Acc) when H >= $A, H =< $Z ->\n    H2 = H + 32,\n    to_lower(T, <<Acc/binary, H2>>);\nto_lower(<<H, T/binary>>, Acc) ->\n    to_lower(T, <<Acc/binary, H>>).\n\n-spec to_upper(Bin :: binary()) -> binary().\nto_upper(Bin) ->\n    to_upper(Bin, <<>>).\n\nto_upper(<<>>, Acc) ->\n    Acc;\nto_upper(<<H, T/binary>>, Acc) when H >= $a, H =< $z ->\n    H2 = H - 32,\n    to_upper(T, <<Acc/binary, H2>>);\nto_upper(<<H, T/binary>>, Acc) ->\n    to_upper(T, <<Acc/binary, H>>).\n\n-spec all(Fun :: function(), Binary :: binary()) -> boolean().\nall(_Fun, <<>>) ->\n    true;\nall(Fun, Binary) ->\n    Res = <<<<X/integer>> || <<X>> <= Binary, Fun(X)>>,\n    Binary == Res.\n%all(Fun, <<H, Tail/binary>>) ->\n%\tFun(H) =:= true andalso all(Fun, Tail).\n\n%% this is a cool hack to very quickly reverse a binary\n-spec reverse(Bin :: binary()) -> binary().\nreverse(Bin) ->\n    Size = byte_size(Bin) * 8,\n    <<T:Size/integer-little>> = Bin,\n    <<T:Size/integer-big>>.\n\n%% reverse a string into a binary - can be faster than lists:reverse on large\n%% lists, even if you run binary_to_string on the result. For smaller strings\n%% it's probably slower (but still not that bad).\n-spec reverse_str_to_bin(String :: string()) -> binary().\nreverse_str_to_bin(String) ->\n    reverse(list_to_binary(String)).\n\n-spec join(Binaries :: [binary() | list()], Glue :: binary() | list()) -> binary().\njoin(Binaries, Glue) ->\n    join(Binaries, Glue, []).\n\njoin([H], _Glue, Acc) ->\n    list_to_binary(lists:reverse([H | Acc]));\njoin([H | T], Glue, Acc) ->\n    join(T, Glue, [Glue, H | Acc]);\njoin([], _Glue, _Acc) ->\n    <<\"\">>.\n"
  },
  {
    "path": "src/gen_smtp.app.src",
    "content": "{application, gen_smtp, [\n    {description, \"The extensible Erlang SMTP client and server library.\"},\n    {vsn, \"1.3.0\"},\n    {applications, [kernel, stdlib, crypto, asn1, public_key, ssl, ranch]},\n    {registered, []},\n    {licenses, [\"BSD-2-Clause\"]},\n    {links, [{\"GitHub\", \"https://github.com/gen-smtp/gen_smtp\"}]},\n    {exclude_files, [\"src/smtp_rfc822_parse.erl\"]}\n]}.\n"
  },
  {
    "path": "src/gen_smtp_client.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc A simple SMTP client used for sending mail - assumes relaying via a\n%% smarthost.\n\n-module(gen_smtp_client).\n\n-define(DEFAULT_OPTIONS, [\n    % whether to connect on 465 in ssl mode\n    {ssl, false},\n    % always, never, if_available\n    {tls, if_available},\n    % used in ssl:connect, http://erlang.org/doc/man/ssl.html\n    {tls_options, [{versions, ['tlsv1', 'tlsv1.1', 'tlsv1.2']}]},\n    {auth, if_available},\n    {hostname, smtp_util:guess_FQDN()},\n    % how many retries per smtp host on temporary failure\n    {retries, 1},\n    {on_transaction_error, quit},\n    % smtp, lmtp\n    {protocol, smtp}\n]).\n\n-define(AUTH_PREFERENCE, [\n    \"CRAM-MD5\",\n    \"LOGIN\",\n    \"PLAIN\",\n    \"XOAUTH2\"\n]).\n\n-define(TIMEOUT, 1200000).\n\n-ifdef(TEST).\n-include_lib(\"eunit/include/eunit.hrl\").\n-compile([export_all, nowarn_export_all]).\n-else.\n-export([send/2, send/3, send_blocking/2, open/1, deliver/2, close/1]).\n-endif.\n\n-export_type([\n    smtp_client_socket/0,\n    email/0,\n    email_address/0,\n    options/0,\n    callback/0,\n    smtp_session_error/0,\n    host_failure/0,\n    failure/0,\n    validate_options_error/0\n]).\n\n-type email_address() :: string() | binary().\n-type email() :: {\n    From :: email_address(),\n    To :: [email_address(), ...],\n    Body :: string() | binary() | fun(() -> string() | binary())\n}.\n\n-type options() :: [\n    {ssl, boolean()}\n    | {tls, always | never | if_available}\n    % ssl:option() / ssl:tls_client_option()\n    | {tls_options, list()}\n    | {sockopts, [gen_tcp:connect_option()]}\n    | {port, inet:port_number()}\n    | {timeout, timeout()}\n    | {relay, inet:ip_address() | inet:hostname()}\n    | {no_mx_lookups, boolean()}\n    | {auth, always | never | if_available}\n    | {hostname, string()}\n    | {retries, non_neg_integer()}\n    | {username, string()}\n    | {password, string()}\n    | {trace_fun, fun((Fmt :: string(), Args :: [any()]) -> any())}\n    | {on_transaction_error, quit | reset}\n    | {protocol, smtp | lmtp}\n].\n\n-type extensions() :: [{binary(), binary()}].\n\n-record(smtp_client_socket, {\n    socket :: smtp_socket:socket(),\n    host :: string(),\n    extensions :: list(),\n    options :: list()\n}).\n-opaque smtp_client_socket() :: #smtp_client_socket{}.\n\n-type callback() :: fun(\n    (\n        {exit, any()}\n        | smtp_session_error()\n        | {ok, binary()}\n    ) -> any()\n).\n\n%% Smth that is thrown from inner SMTP functions\n\n% server's 5xx response\n-type permanent_failure_reason() ::\n    binary()\n    | auth_failed\n    | ssl_not_started.\n%server's 4xx response\n-type temporary_failure_reason() ::\n    binary()\n    | tls_failed.\n-type validate_options_error() ::\n    no_relay\n    | invalid_port\n    | no_credentials.\n-type failure() ::\n    {temporary_failure, temporary_failure_reason()}\n    | {permanent_failure, permanent_failure_reason()}\n    | {missing_requirement, auth | tls}\n    | {unexpected_response, [binary()]}\n    | {network_failure, {error, timeout | inet:posix()}}.\n-type smtp_host() :: inet:hostname().\n-type host_failure() ::\n    {temporary_failure, smtp_host(), temporary_failure_reason()}\n    | {permanent_failure, smtp_host(), permanent_failure_reason()}\n    | {missing_requirement, smtp_host(), auth | tls}\n    | {unexpected_response, smtp_host(), [binary()]}\n    | {network_failure, smtp_host(), {error, timeout | inet:posix()}}.\n-type smtp_session_error() ::\n    {error, no_more_hosts | send, {permanent_failure, smtp_host(), permanent_failure_reason()}}\n    | {error, retries_exceeded | send, host_failure()}.\n\n-spec send(Email :: email(), Options :: options()) ->\n    {'ok', pid()} | {'error', validate_options_error()}.\n%% @doc Send an email in a non-blocking fashion via a spawned_linked process.\n%% The process will exit abnormally on a send failure.\nsend(Email, Options) ->\n    send(Email, Options, undefined).\n\n%% @doc Send an email nonblocking and invoke a callback with the result of the send.\n%% The callback will receive either `{ok, Receipt}' where Receipt is the SMTP server's receipt\n%% If it's using LMTP protocol, the callback will receive a list with the delivery response for each address `{ok, [{\"foo@bar.com\", \"250 ok\"}, {\"bar@foo.com\", \"452 <bar@foo.com> is temporarily over quota\"}]}`.\n%% identifier,  `{error, Type, Message}' or `{exit, ExitReason}', as the single argument.\n-spec send(Email :: email(), Options :: options(), Callback :: callback() | 'undefined') ->\n    {'ok', pid()} | {'error', validate_options_error()}.\nsend(Email, Options, Callback) ->\n    NewOptions = lists:ukeymerge(\n        1,\n        lists:sort(Options),\n        lists:sort(?DEFAULT_OPTIONS)\n    ),\n    case check_options(NewOptions) of\n        ok ->\n            Pid = spawn_link(\n                fun() ->\n                    try send_it(Email, NewOptions) of\n                        {error, _Type, _Reason} = Error when is_function(Callback, 1) ->\n                            Callback(Error);\n                        {error, _Type, _Reason} = Error ->\n                            exit(Error);\n                        Receipt when is_function(Callback, 1) ->\n                            Callback({ok, Receipt});\n                        _Receipt ->\n                            ok\n                    catch\n                        exit:Reason when is_function(Callback, 1) ->\n                            Callback({exit, Reason})\n                    end\n                end\n            ),\n            {ok, Pid};\n        {error, Reason} ->\n            {error, Reason}\n    end.\n\n-spec send_blocking(Email :: email(), Options :: options()) ->\n    binary()\n    | [{binary(), binary()}, ...]\n    | smtp_session_error()\n    | {error, validate_options_error()}.\n%% @doc Send an email and block waiting for the reply. Returns either a binary that contains\n%% If it's using LMTP protocol, it will return a list with the delivery response for each address `[{\"foo@bar.com\", \"250 ok\"}, {\"bar@foo.com\", \"452 <bar@foo.com> is temporarily over quota\"}]`.\n%% the SMTP server's receipt or `{error, Type, Message}' or `{error, Reason}'.\nsend_blocking(Email, Options) ->\n    NewOptions = lists:ukeymerge(\n        1,\n        lists:sort(Options),\n        lists:sort(?DEFAULT_OPTIONS)\n    ),\n    case check_options(NewOptions) of\n        ok ->\n            send_it(Email, NewOptions);\n        {error, Reason} ->\n            {error, Reason}\n    end.\n\n-spec open(Options :: options()) ->\n    {ok, SocketDescriptor :: smtp_client_socket()}\n    | smtp_session_error()\n    | {error, bad_option, validate_options_error()}.\n%% @doc Open a SMTP client socket with the provided options\n%% Once the socket has been opened, you can use it with deliver/2.\nopen(Options) ->\n    NewOptions = lists:ukeymerge(\n        1,\n        lists:sort(Options),\n        lists:sort(?DEFAULT_OPTIONS)\n    ),\n    case check_options(NewOptions) of\n        ok ->\n            RelayDomain = proplists:get_value(relay, NewOptions),\n            MXRecords =\n                case proplists:get_value(no_mx_lookups, NewOptions) of\n                    true ->\n                        [];\n                    _ ->\n                        smtp_util:mxlookup(RelayDomain)\n                end,\n            trace(Options, \"MX records for ~s are ~p~n\", [RelayDomain, MXRecords]),\n            Hosts =\n                case MXRecords of\n                    [] ->\n                        % maybe we're supposed to relay to a host directly\n                        [{0, RelayDomain}];\n                    _ ->\n                        MXRecords\n                end,\n            try_smtp_sessions(Hosts, NewOptions, []);\n        {error, Reason} ->\n            {error, bad_option, Reason}\n    end.\n\n-spec deliver(Socket :: smtp_client_socket(), Email :: email()) ->\n    {'ok', Receipt :: binary() | [{binary(), binary()}, ...]} | {error, FailMsg :: failure()}.\n%% @doc Deliver an email on an open smtp client socket.\n%% For use with a socket opened with open/1. The socket can be reused as long as the previous call to deliver/2 returned `{ok, Receipt}'.\n%% If it's using LMTP protocol, it will return a list with the delivery response for each address `{ok, [{\"foo@bar.com\", \"250 ok\"}, {\"bar@foo.com\", \"452 <bar@foo.com> is temporarily over quota\"}]}`.\n%% If the previous call to deliver/2 returned `{error, FailMsg}' and the option `{on_transaction_error, reset}' was given in the open/1 call,\n%% the socket <em>may</em> still be reused.\ndeliver(#smtp_client_socket{} = SmtpClientSocket, Email) ->\n    #smtp_client_socket{\n        socket = Socket,\n        extensions = Extensions,\n        options = Options\n    } = SmtpClientSocket,\n    try\n        Receipt = try_sending_it(Email, Socket, Extensions, Options),\n        {ok, Receipt}\n    catch\n        throw:FailMsg ->\n            {error, FailMsg}\n    end.\n\n-spec close(Socket :: smtp_client_socket()) -> ok.\n%% @doc Close an open smtp client socket opened with open/1.\nclose(#smtp_client_socket{socket = Socket}) ->\n    quit(Socket).\n\n-spec send_it(Email :: email(), Options :: options()) ->\n    binary()\n    | smtp_session_error().\nsend_it(Email, Options) ->\n    RelayDomain = to_string(proplists:get_value(relay, Options)),\n    MXRecords =\n        case proplists:get_value(no_mx_lookups, Options) of\n            true ->\n                [];\n            _ ->\n                smtp_util:mxlookup(RelayDomain)\n        end,\n    trace(Options, \"MX records for ~s are ~p~n\", [RelayDomain, MXRecords]),\n    Hosts =\n        case MXRecords of\n            [] ->\n                % maybe we're supposed to relay to a host directly\n                [{0, RelayDomain}];\n            _ ->\n                MXRecords\n        end,\n    case try_smtp_sessions(Hosts, Options, []) of\n        {error, _, _} = Error ->\n            Error;\n        {ok, ClientSocket} ->\n            #smtp_client_socket{\n                socket = Socket,\n                host = Host,\n                extensions = Extensions,\n                options = Options1\n            } = ClientSocket,\n            try\n                try_sending_it(Email, Socket, Extensions, Options1)\n            catch\n                throw:{FailureType, Message} ->\n                    {error, send, {FailureType, Host, Message}}\n            after\n                quit(Socket)\n            end\n    end.\n\n-spec try_smtp_sessions(\n    Hosts :: [{non_neg_integer(), string()}, ...], Options :: options(), RetryList :: list()\n) ->\n    {ok, smtp_client_socket()}\n    | smtp_session_error().\ntry_smtp_sessions([{_Distance, Host} | _Tail] = Hosts, Options, RetryList) ->\n    try\n        {ok, open_smtp_session(Host, Options)}\n    catch\n        throw:FailMsg ->\n            handle_smtp_throw(FailMsg, Hosts, Options, RetryList)\n    end.\n\n-spec handle_smtp_throw(failure(), [{non_neg_integer(), smtp_host()}], options(), list()) ->\n    {ok, smtp_client_socket()}\n    | smtp_session_error().\nhandle_smtp_throw({permanent_failure, Message}, [{_Distance, Host} | _Tail], _Options, _RetryList) ->\n    % permanent failure means no retries, and don't even continue with other hosts\n    {error, no_more_hosts, {permanent_failure, Host, Message}};\nhandle_smtp_throw(\n    {temporary_failure, tls_failed}, [{_Distance, Host} | _Tail] = Hosts, Options, RetryList\n) ->\n    % Could not start the TLS handshake; if tls is optional then try without TLS\n    case proplists:get_value(tls, Options) of\n        if_available ->\n            NoTLSOptions = [{tls, never} | proplists:delete(tls, Options)],\n            try open_smtp_session(Host, NoTLSOptions) of\n                Res -> {ok, Res}\n            catch\n                throw:FailMsg ->\n                    handle_smtp_throw(FailMsg, Hosts, Options, RetryList)\n            end;\n        _ ->\n            try_next_host({temporary_failure, tls_failed}, Hosts, Options, RetryList)\n    end;\nhandle_smtp_throw(FailMsg, Hosts, Options, RetryList) ->\n    try_next_host(FailMsg, Hosts, Options, RetryList).\n\ntry_next_host({FailureType, Message}, [{_Distance, Host} | _Tail] = Hosts, Options, RetryList) ->\n    Retries = proplists:get_value(retries, Options),\n    RetryCount = proplists:get_value(Host, RetryList),\n    case fetch_next_host(Retries, RetryCount, Hosts, RetryList, Options) of\n        {[], _NewRetryList} ->\n            {error, retries_exceeded, {FailureType, Host, Message}};\n        {NewHosts, NewRetryList} ->\n            try_smtp_sessions(NewHosts, Options, NewRetryList)\n    end.\n\nfetch_next_host(Retries, RetryCount, [{_Distance, Host} | Tail], RetryList, Options) when\n    is_integer(RetryCount), RetryCount >= Retries\n->\n    % out of chances\n    trace(Options, \"retries for ~s exceeded (~p of ~p)~n\", [Host, RetryCount, Retries]),\n    {Tail, lists:keydelete(Host, 1, RetryList)};\nfetch_next_host(Retries, RetryCount, [{Distance, Host} | Tail], RetryList, Options) when\n    is_integer(RetryCount)\n->\n    trace(Options, \"scheduling ~s for retry (~p of ~p)~n\", [Host, RetryCount, Retries]),\n    {Tail ++ [{Distance, Host}], lists:keydelete(Host, 1, RetryList) ++ [{Host, RetryCount + 1}]};\nfetch_next_host(0, _RetryCount, [{_Distance, Host} | Tail], RetryList, _Options) ->\n    % done retrying completely\n    {Tail, lists:keydelete(Host, 1, RetryList)};\nfetch_next_host(Retries, _RetryCount, [{Distance, Host} | Tail], RetryList, Options) ->\n    % otherwise...\n    trace(Options, \"scheduling ~s for retry (~p of ~p)~n\", [Host, 1, Retries]),\n    {Tail ++ [{Distance, Host}], lists:keydelete(Host, 1, RetryList) ++ [{Host, 1}]}.\n\n-spec open_smtp_session(Host :: string(), Options :: options()) -> smtp_client_socket().\nopen_smtp_session(Host, Options) ->\n    {ok, Socket, _Host2, Banner} = connect(Host, Options),\n    trace(Options, \"connected to ~s; banner was ~s~n\", [Host, Banner]),\n    {ok, Extensions} = try_EHLO(Socket, Options),\n    trace(Options, \"Extensions are ~p~n\", [Extensions]),\n    {Socket2, Extensions2} = try_STARTTLS(Socket, Options, Extensions),\n    trace(Options, \"Extensions are ~p~n\", [Extensions2]),\n    Authed = try_AUTH(Socket2, Options, proplists:get_value(<<\"AUTH\">>, Extensions2)),\n    trace(Options, \"Authentication status is ~p~n\", [Authed]),\n    #smtp_client_socket{\n        socket = Socket2,\n        host = Host,\n        extensions = Extensions,\n        options = Options\n    }.\n\n-spec try_sending_it(\n    Email :: email(),\n    Socket :: smtp_socket:socket(),\n    Extensions :: extensions(),\n    Options :: options()\n) -> binary() | [{binary(), binary()}, ...].\ntry_sending_it({From, To, Body}, Socket, Extensions, Options) ->\n    try_MAIL_FROM(From, Socket, Extensions, Options),\n    try_RCPT_TO(To, Socket, Extensions, Options),\n    case proplists:get_value(protocol, Options) of\n        smtp -> try_DATA(Body, Socket, Extensions, Options);\n        lmtp -> try_lmtp_DATA(Body, To, Socket, Extensions, Options)\n    end.\n\n-spec try_MAIL_FROM(\n    From :: email_address(),\n    Socket :: smtp_socket:socket(),\n    Extensions :: extensions(),\n    Options :: options()\n) -> true.\ntry_MAIL_FROM(From, Socket, Extensions, Options) when is_binary(From) ->\n    try_MAIL_FROM(binary_to_list(From), Socket, Extensions, Options);\ntry_MAIL_FROM(\"<\" ++ _ = From, Socket, _Extensions, Options) ->\n    OnTxError = proplists:get_value(on_transaction_error, Options),\n    % TODO do we need to bother with SIZE?\n    smtp_socket:send(Socket, [\"MAIL FROM:\", From, \"\\r\\n\"]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"250\", _Rest/binary>>} ->\n            true;\n        {ok, <<\"4\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"5\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            trace(Options, \"Mail FROM rejected: ~p~n\", [Msg]),\n            ok = rset_or_quit(Socket),\n            throw({permanent_failure, Msg});\n        {ok, Msg} ->\n            trace(Options, \"Mail FROM rejected: ~p~n\", [Msg]),\n            quit(Socket),\n            throw({permanent_failure, Msg})\n    end;\ntry_MAIL_FROM(From, Socket, Extension, Options) ->\n    % someone was bad and didn't put in the angle brackets\n    try_MAIL_FROM(\"<\" ++ From ++ \">\", Socket, Extension, Options).\n\n-spec try_RCPT_TO(\n    Tos :: [email_address()],\n    Socket :: smtp_socket:socket(),\n    Extensions :: extensions(),\n    Options :: options()\n) -> true.\ntry_RCPT_TO([], _Socket, _Extensions, _Options) ->\n    true;\ntry_RCPT_TO([To | Tail], Socket, Extensions, Options) when is_binary(To) ->\n    try_RCPT_TO([binary_to_list(To) | Tail], Socket, Extensions, Options);\ntry_RCPT_TO([\"<\" ++ _ = To | Tail], Socket, Extensions, Options) ->\n    OnTxError = proplists:get_value(on_transaction_error, Options),\n    smtp_socket:send(Socket, [\"RCPT TO:\", To, \"\\r\\n\"]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"250\", _Rest/binary>>} ->\n            try_RCPT_TO(Tail, Socket, Extensions, Options);\n        {ok, <<\"251\", _Rest/binary>>} ->\n            try_RCPT_TO(Tail, Socket, Extensions, Options);\n        {ok, <<\"4\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"5\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({permanent_failure, Msg});\n        {ok, Msg} ->\n            quit(Socket),\n            throw({permanent_failure, Msg})\n    end;\ntry_RCPT_TO([To | Tail], Socket, Extensions, Options) ->\n    % someone was bad and didn't put in the angle brackets\n    try_RCPT_TO([\"<\" ++ To ++ \">\" | Tail], Socket, Extensions, Options).\n\n-spec try_DATA(\n    Body :: binary() | function(),\n    Socket :: smtp_socket:socket(),\n    Extensions :: extensions(),\n    Options :: options()\n) -> binary().\ntry_DATA(Body, Socket, Extensions, Options) when is_function(Body) ->\n    try_DATA(Body(), Socket, Extensions, Options);\ntry_DATA(Body, Socket, _Extensions, Options) ->\n    OnTxError = proplists:get_value(on_transaction_error, Options),\n    smtp_socket:send(Socket, \"DATA\\r\\n\"),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"354\", _Rest/binary>>} ->\n            %% Escape period at start of line (rfc5321 4.5.2)\n            EscapedBody = re:replace(Body, <<\"^\\\\\\.\">>, <<\"..\">>, [\n                global, multiline, {return, binary}\n            ]),\n            smtp_socket:send(Socket, [EscapedBody, \"\\r\\n.\\r\\n\"]),\n            case read_possible_multiline_reply(Socket) of\n                {ok, <<\"250 \", Receipt/binary>>} ->\n                    Receipt;\n                {ok, <<\"4\", _Rest2/binary>> = Msg} when OnTxError =:= reset ->\n                    throw({temporary_failure, Msg});\n                {ok, <<\"4\", _Rest2/binary>> = Msg} ->\n                    quit(Socket),\n                    throw({temporary_failure, Msg});\n                {ok, <<\"5\", _Rest2/binary>> = Msg} when OnTxError =:= reset ->\n                    throw({permanent_failure, Msg});\n                {ok, Msg} ->\n                    quit(Socket),\n                    throw({permanent_failure, Msg})\n            end;\n        {ok, <<\"4\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"5\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({permanent_failure, Msg});\n        {ok, Msg} ->\n            quit(Socket),\n            throw({permanent_failure, Msg})\n    end.\n\n-spec try_lmtp_DATA(\n    Body :: binary() | function(),\n    To :: [binary(), ...],\n    Socket :: smtp_socket:socket(),\n    Extensions :: extensions(),\n    Options :: options()\n) -> binary() | [{email_address(), binary() | string()}, ...].\ntry_lmtp_DATA(Body, To, Socket, Extensions, Options) when is_function(Body) ->\n    try_lmtp_DATA(Body(), To, Socket, Extensions, Options);\ntry_lmtp_DATA(Body, To, Socket, _Extensions, Options) ->\n    OnTxError = proplists:get_value(on_transaction_error, Options),\n    smtp_socket:send(Socket, \"DATA\\r\\n\"),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"354\", _Rest/binary>>} ->\n            %% Escape period at start of line (rfc5321 4.5.2)\n            EscapedBody = re:replace(Body, <<\"^\\\\\\.\">>, <<\"..\">>, [\n                global, multiline, {return, binary}\n            ]),\n            smtp_socket:send(Socket, [EscapedBody, \"\\r\\n.\\r\\n\"]),\n            lists:map(\n                fun(Recipient) ->\n                    {ok, Receipt} = read_possible_multiline_reply(Socket),\n                    {Recipient, Receipt}\n                end,\n                To\n            );\n        {ok, <<\"4\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, <<\"5\", _Rest/binary>> = Msg} when OnTxError =:= reset ->\n            rset_or_quit(Socket),\n            throw({permanent_failure, Msg});\n        {ok, Msg} ->\n            quit(Socket),\n            throw({permanent_failure, Msg})\n    end.\n\n-spec try_AUTH(Socket :: smtp_socket:socket(), Options :: options(), AuthTypes :: [string()]) ->\n    boolean().\ntry_AUTH(Socket, Options, []) ->\n    case proplists:get_value(auth, Options) of\n        always ->\n            quit(Socket),\n            erlang:throw({missing_requirement, auth});\n        _ ->\n            false\n    end;\ntry_AUTH(Socket, Options, undefined) ->\n    case proplists:get_value(auth, Options) of\n        always ->\n            quit(Socket),\n            erlang:throw({missing_requirement, auth});\n        _ ->\n            false\n    end;\ntry_AUTH(Socket, Options, AuthTypes) ->\n    case\n        proplists:is_defined(username, Options) and\n            proplists:is_defined(password, Options) and\n            (proplists:get_value(auth, Options) =/= never)\n    of\n        false ->\n            case proplists:get_value(auth, Options) of\n                always ->\n                    quit(Socket),\n                    erlang:throw({missing_requirement, auth});\n                _ ->\n                    false\n            end;\n        true ->\n            Username = to_binary(proplists:get_value(username, Options)),\n            Password = to_binary(proplists:get_value(password, Options)),\n            trace(Options, \"Auth types: ~p~n\", [AuthTypes]),\n            Types = re:split(AuthTypes, \" \", [{return, list}, trim]),\n            case do_AUTH(Socket, Username, Password, Types, Options) of\n                false ->\n                    case proplists:get_value(auth, Options) of\n                        always ->\n                            quit(Socket),\n                            erlang:throw({permanent_failure, auth_failed});\n                        _ ->\n                            false\n                    end;\n                true ->\n                    true\n            end\n    end.\n\nto_string(String) when is_list(String) -> String;\nto_string(Binary) when is_binary(Binary) -> binary_to_list(Binary).\n\nto_binary(String) when is_binary(String) -> String;\nto_binary(String) when is_list(String) -> list_to_binary(String).\n\n-spec do_AUTH(\n    Socket :: smtp_socket:socket(),\n    Username :: binary(),\n    Password :: binary(),\n    Types :: [string()],\n    Options :: options()\n) -> boolean().\ndo_AUTH(Socket, Username, Password, Types, Options) ->\n    FixedTypes = [string:to_upper(X) || X <- Types],\n    trace(Options, \"Fixed types: ~p~n\", [FixedTypes]),\n    AllowedTypes = [X || X <- ?AUTH_PREFERENCE, lists:member(X, FixedTypes)],\n    trace(Options, \"available authentication types, in order of preference: ~p~n\", [AllowedTypes]),\n    do_AUTH_each(Socket, Username, Password, AllowedTypes, Options).\n\n-spec do_AUTH_each(\n    Socket :: smtp_socket:socket(),\n    Username :: binary(),\n    Password :: binary(),\n    AuthTypes :: [string()],\n    Options :: options()\n) -> boolean().\ndo_AUTH_each(_Socket, _Username, _Password, [], _Options) ->\n    false;\ndo_AUTH_each(Socket, Username, Password, [\"CRAM-MD5\" | Tail], Options) ->\n    smtp_socket:send(Socket, \"AUTH CRAM-MD5\\r\\n\"),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"334 \", Rest/binary>>} ->\n            Seed64 = binstr:strip(binstr:strip(Rest, right, $\\n), right, $\\r),\n            Seed = base64:decode(Seed64),\n            Digest = smtp_util:compute_cram_digest(Password, Seed),\n            String = base64:encode(list_to_binary([Username, \" \", Digest])),\n            smtp_socket:send(Socket, [String, \"\\r\\n\"]),\n            case read_possible_multiline_reply(Socket) of\n                {ok, <<\"235\", _Rest/binary>>} ->\n                    trace(Options, \"authentication accepted~n\", []),\n                    true;\n                {ok, Msg} ->\n                    trace(Options, \"authentication rejected: ~s~n\", [Msg]),\n                    do_AUTH_each(Socket, Username, Password, Tail, Options)\n            end;\n        {ok, Something} ->\n            trace(Options, \"got ~s~n\", [Something]),\n            do_AUTH_each(Socket, Username, Password, Tail, Options)\n    end;\ndo_AUTH_each(Socket, Username, Password, [\"XOAUTH2\" | Tail], Options) ->\n    Str = base64:encode(list_to_binary([\"user=\", Username, 1, \"auth=Bearer \", Password, 1, 1])),\n    smtp_socket:send(Socket, [\"AUTH XOAUTH2 \", Str, \"\\r\\n\"]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"235\", _Rest/binary>>} ->\n            true;\n        {ok, _Msg} ->\n            do_AUTH_each(Socket, Username, Password, Tail, Options)\n    end;\ndo_AUTH_each(Socket, Username, Password, [\"LOGIN\" | Tail], Options) ->\n    smtp_socket:send(Socket, \"AUTH LOGIN\\r\\n\"),\n    {ok, Prompt} = read_possible_multiline_reply(Socket),\n    case is_auth_username_prompt(Prompt) of\n        true ->\n            %% base64 Username: or username:\n            trace(Options, \"username prompt~n\", []),\n            U = base64:encode(Username),\n            smtp_socket:send(Socket, [U, \"\\r\\n\"]),\n            {ok, Prompt2} = read_possible_multiline_reply(Socket),\n            case is_auth_password_prompt(Prompt2) of\n                true ->\n                    %% base64 Password: or password:\n                    trace(Options, \"password prompt~n\", []),\n                    P = base64:encode(Password),\n                    smtp_socket:send(Socket, [P, \"\\r\\n\"]),\n                    case read_possible_multiline_reply(Socket) of\n                        {ok, <<\"235 \", _Rest/binary>>} ->\n                            trace(Options, \"authentication accepted~n\", []),\n                            true;\n                        {ok, Msg} ->\n                            trace(Options, \"password rejected: ~s\", [Msg]),\n                            do_AUTH_each(Socket, Username, Password, Tail, Options)\n                    end;\n                false ->\n                    trace(Options, \"username rejected: ~s\", [Prompt2]),\n                    do_AUTH_each(Socket, Username, Password, Tail, Options)\n            end;\n        false ->\n            trace(Options, \"got ~s~n\", [Prompt]),\n            do_AUTH_each(Socket, Username, Password, Tail, Options)\n    end;\ndo_AUTH_each(Socket, Username, Password, [\"PLAIN\" | Tail], Options) ->\n    AuthString = base64:encode(<<0, Username/binary, 0, Password/binary>>),\n    smtp_socket:send(Socket, [\"AUTH PLAIN \", AuthString, \"\\r\\n\"]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"235\", _Rest/binary>>} ->\n            trace(Options, \"authentication accepted~n\", []),\n            true;\n        Else ->\n            % TODO do we need to bother trying the multi-step PLAIN?\n            trace(Options, \"authentication rejected ~p~n\", [Else]),\n            do_AUTH_each(Socket, Username, Password, Tail, Options)\n    end;\ndo_AUTH_each(Socket, Username, Password, [Type | Tail], Options) ->\n    trace(Options, \"unsupported AUTH type ~s~n\", [Type]),\n    do_AUTH_each(Socket, Username, Password, Tail, Options).\n\nis_auth_username_prompt(<<\"334 VXNlcm5hbWU6\\r\\n\">>) -> true;\nis_auth_username_prompt(<<\"334 dXNlcm5hbWU6\\r\\n\">>) -> true;\nis_auth_username_prompt(<<\"334 VXNlcm5hbWU6 \", _/binary>>) -> true;\nis_auth_username_prompt(<<\"334 dXNlcm5hbWU6 \", _/binary>>) -> true;\nis_auth_username_prompt(_) -> false.\n\nis_auth_password_prompt(<<\"334 UGFzc3dvcmQ6\\r\\n\">>) -> true;\nis_auth_password_prompt(<<\"334 cGFzc3dvcmQ6\\r\\n\">>) -> true;\nis_auth_password_prompt(<<\"334 UGFzc3dvcmQ6 \", _/binary>>) -> true;\nis_auth_password_prompt(<<\"334 cGFzc3dvcmQ6 \", _/binary>>) -> true;\nis_auth_password_prompt(_) -> false.\n\n-spec try_EHLO(Socket :: smtp_socket:socket(), Options :: options()) -> {ok, extensions()}.\ntry_EHLO(Socket, Options) ->\n    Hallo =\n        case proplists:get_value(protocol, Options, smtp) of\n            lmtp -> \"LHLO \";\n            _ -> \"EHLO \"\n        end,\n    ok = smtp_socket:send(Socket, [\n        Hallo, proplists:get_value(hostname, Options, smtp_util:guess_FQDN()), \"\\r\\n\"\n    ]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"500\", _Rest/binary>>} ->\n            % Unrecognized command, fall back to HELO\n            try_HELO(Socket, Options);\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, Reply} ->\n            {ok, parse_extensions(Reply, Options)}\n    end.\n\n-spec try_HELO(Socket :: smtp_socket:socket(), Options :: options()) -> {ok, list()}.\ntry_HELO(Socket, Options) ->\n    ok = smtp_socket:send(Socket, [\n        \"HELO \", proplists:get_value(hostname, Options, smtp_util:guess_FQDN()), \"\\r\\n\"\n    ]),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"250\", _Rest/binary>>} ->\n            {ok, []};\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            throw({temporary_failure, Msg});\n        {ok, Msg} ->\n            quit(Socket),\n            throw({permanent_failure, Msg})\n    end.\n\n% check if we should try to do TLS\n-spec try_STARTTLS(\n    Socket :: smtp_socket:socket(), Options :: options(), Extensions :: extensions()\n) -> {smtp_socket:socket(), extensions()}.\ntry_STARTTLS(Socket, Options, Extensions) ->\n    case {proplists:get_value(tls, Options), proplists:get_value(<<\"STARTTLS\">>, Extensions)} of\n        {Atom, true} when Atom =:= always; Atom =:= if_available ->\n            trace(Options, \"Starting TLS~n\", []),\n            case {do_STARTTLS(Socket, Options), Atom} of\n                {false, always} ->\n                    trace(Options, \"TLS failed~n\", []),\n                    quit(Socket),\n                    erlang:throw({temporary_failure, tls_failed});\n                {false, if_available} ->\n                    trace(Options, \"TLS failed~n\", []),\n                    {Socket, Extensions};\n                {{S, E}, _} ->\n                    trace(Options, \"TLS started~n\", []),\n                    {S, E}\n            end;\n        {always, _} ->\n            quit(Socket),\n            erlang:throw({missing_requirement, tls});\n        _ ->\n            trace(Options, \"TLS not requested ~p~n\", [Options]),\n            {Socket, Extensions}\n    end.\n\n%% attempt to upgrade socket to TLS\n-spec do_STARTTLS(Socket :: smtp_socket:socket(), Options :: options()) ->\n    {smtp_socket:socket(), extensions()} | false.\ndo_STARTTLS(Socket, Options) ->\n    smtp_socket:send(Socket, \"STARTTLS\\r\\n\"),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"220\", _Rest/binary>>} ->\n            case\n                catch smtp_socket:to_ssl_client(\n                    Socket, [binary | proplists:get_value(tls_options, Options, [])], 5000\n                )\n            of\n                {ok, NewSocket} ->\n                    %NewSocket;\n                    {ok, Extensions} = try_EHLO(NewSocket, Options),\n                    {NewSocket, Extensions};\n                {'EXIT', Reason} ->\n                    quit(Socket),\n                    error_logger:error_msg(\"Error in ssl upgrade: ~p.~n\", [Reason]),\n                    erlang:throw({temporary_failure, tls_failed});\n                {error, closed} ->\n                    quit(Socket),\n                    error_logger:error_msg(\"Error in ssl upgrade: socket closed.~n\"),\n                    erlang:throw({temporary_failure, tls_failed});\n                {error, ssl_not_started} ->\n                    quit(Socket),\n                    error_logger:error_msg(\"SSL not started.~n\"),\n                    erlang:throw({permanent_failure, ssl_not_started});\n                Else ->\n                    trace(Options, \"~p~n\", [Else]),\n                    false\n            end;\n        {ok, <<\"4\", _Rest/binary>> = Msg} ->\n            quit(Socket),\n            erlang:throw({temporary_failure, Msg});\n        {ok, Msg} ->\n            quit(Socket),\n            erlang:throw({permanent_failure, Msg})\n    end.\n\n%% try connecting to a host\nconnect(Host, Options) when is_binary(Host) ->\n    connect(binary_to_list(Host), Options);\nconnect(Host, Options) ->\n    AddSockOpts =\n        case proplists:get_value(sockopts, Options) of\n            undefined -> [];\n            Other -> Other\n        end,\n    SockOpts = [binary, {packet, line}, {keepalive, true}, {active, false} | AddSockOpts],\n    Proto =\n        case proplists:get_value(ssl, Options) of\n            true ->\n                ssl;\n            _ ->\n                tcp\n        end,\n    Port =\n        case proplists:get_value(port, Options) of\n            undefined when Proto =:= ssl ->\n                465;\n            OPort when is_integer(OPort) ->\n                OPort;\n            _ ->\n                25\n        end,\n    Timeout =\n        case proplists:get_value(timeout, Options) of\n            undefined -> 5000;\n            OTimeout -> OTimeout\n        end,\n    case smtp_socket:connect(Proto, Host, Port, SockOpts, Timeout) of\n        {ok, Socket} ->\n            case read_possible_multiline_reply(Socket) of\n                {ok, <<\"220\", Banner/binary>>} ->\n                    {ok, Socket, Host, Banner};\n                {ok, <<\"4\", _Rest/binary>> = Msg} ->\n                    quit(Socket),\n                    throw({temporary_failure, Msg});\n                {ok, Msg} ->\n                    quit(Socket),\n                    throw({permanent_failure, Msg})\n            end;\n        {error, Reason} ->\n            throw({network_failure, {error, Reason}})\n    end.\n\n%% read a multiline reply (eg. EHLO reply)\n-spec read_possible_multiline_reply(Socket :: smtp_socket:socket()) -> {ok, binary()}.\nread_possible_multiline_reply(Socket) ->\n    case smtp_socket:recv(Socket, 0, ?TIMEOUT) of\n        {ok, Packet} ->\n            case binstr:substr(Packet, 4, 1) of\n                <<\"-\">> ->\n                    Code = binstr:substr(Packet, 1, 3),\n                    read_multiline_reply(Socket, Code, [Packet]);\n                <<\" \">> ->\n                    {ok, Packet};\n                _ ->\n                    quit(Socket),\n                    throw({unexpected_response, Packet})\n            end;\n        Error ->\n            throw({network_failure, Error})\n    end.\n\n-spec read_multiline_reply(Socket :: smtp_socket:socket(), Code :: binary(), Acc :: [binary()]) ->\n    {ok, binary()}.\nread_multiline_reply(Socket, Code, Acc) ->\n    case smtp_socket:recv(Socket, 0, ?TIMEOUT) of\n        {ok, Packet} ->\n            case {binstr:substr(Packet, 1, 3), binstr:substr(Packet, 4, 1)} of\n                {Code, <<\" \">>} ->\n                    {ok, list_to_binary(lists:reverse([Packet | Acc]))};\n                {Code, <<\"-\">>} ->\n                    read_multiline_reply(Socket, Code, [Packet | Acc]);\n                _ ->\n                    quit(Socket),\n                    throw({unexpected_response, lists:reverse([Packet | Acc])})\n            end;\n        Error ->\n            throw({network_failure, Error})\n    end.\n\nrset_or_quit(Socket) ->\n    ok = smtp_socket:send(Socket, \"RSET\\r\\n\"),\n    case read_possible_multiline_reply(Socket) of\n        {ok, <<\"250\", _Rest/binary>>} ->\n            ok;\n        {ok, _Msg} ->\n            quit(Socket)\n    end.\n\nquit(Socket) ->\n    smtp_socket:send(Socket, \"QUIT\\r\\n\"),\n    smtp_socket:close(Socket),\n    ok.\n\n% TODO - more checking\ncheck_options(Options) ->\n    CheckedOptions = [relay, port, auth],\n    lists:foldl(\n        fun(Option, State) ->\n            case State of\n                ok ->\n                    Value = proplists:get_value(Option, Options),\n                    check_option({Option, Value}, Options);\n                Other ->\n                    Other\n            end\n        end,\n        ok,\n        CheckedOptions\n    ).\n\ncheck_option({relay, undefined}, _Options) ->\n    {error, no_relay};\ncheck_option({relay, _}, _Options) ->\n    ok;\ncheck_option({port, undefined}, _Options) ->\n    ok;\ncheck_option({port, Port}, _Options) when is_integer(Port) -> ok;\ncheck_option({port, _}, _Options) ->\n    {error, invalid_port};\ncheck_option({auth, always}, Options) ->\n    case\n        proplists:is_defined(username, Options) and\n            proplists:is_defined(password, Options)\n    of\n        false ->\n            {error, no_credentials};\n        true ->\n            ok\n    end;\ncheck_option({auth, _}, _Options) ->\n    ok.\n\n-spec parse_extensions(Reply :: binary(), Options :: options()) -> extensions().\nparse_extensions(Reply, Options) ->\n    [_ | Reply2] = re:split(Reply, \"\\r\\n\", [{return, binary}, trim]),\n    [\n        begin\n            Body = binstr:substr(Entry, 5),\n            case re:split(Body, \" \", [{return, binary}, trim, {parts, 2}]) of\n                [Verb, Parameters] ->\n                    {binstr:to_upper(Verb), Parameters};\n                [Body] ->\n                    case binstr:strchr(Body, $=) of\n                        0 ->\n                            {binstr:to_upper(Body), true};\n                        _ ->\n                            trace(Options, \"discarding option ~p~n\", [Body]),\n                            []\n                    end\n            end\n        end\n     || Entry <- Reply2\n    ].\n\ntrace(Options, Format, Args) ->\n    case proplists:get_value(trace_fun, Options) of\n        undefined -> ok;\n        F -> F(Format, Args)\n    end.\n\n-ifdef(TEST).\n\nsession_start_test_() ->\n    {foreach, local,\n        fun() ->\n            {ok, ListenSock} = smtp_socket:listen(tcp, 9876),\n            {ListenSock}\n        end,\n        fun({ListenSock}) ->\n            smtp_socket:close(ListenSock)\n        end,\n        [\n            fun({ListenSock}) ->\n                {\"simple session initiation\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"retry on crashed EHLO twice if requested\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {retries, 2}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:close(X),\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:close(Y),\n                    {ok, Z} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Z, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Z, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"retry on crashed EHLO\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    unlink(Pid),\n                    Monitor = erlang:monitor(process, Pid),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:close(X),\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:close(Y),\n                    ?assertEqual({error, timeout}, smtp_socket:accept(ListenSock, 1000)),\n                    receive\n                        {'DOWN', Monitor, _, _, Error} ->\n                            ?assertMatch({error, retries_exceeded, _}, Error)\n                    end,\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"abort on 554 greeting\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    unlink(Pid),\n                    Monitor = erlang:monitor(process, Pid),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"554 get lost, kid\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    receive\n                        {'DOWN', Monitor, _, _, Error} ->\n                            ?assertMatch({error, no_more_hosts, _}, Error)\n                    end,\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"retry on 421 greeting\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"421 can't you see I'm busy?\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"retry on messed up EHLO response\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    unlink(Pid),\n                    Monitor = erlang:monitor(process, Pid),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(\n                        X, \"250-server.example.com EHLO\\r\\n250-AUTH LOGIN PLAIN\\r\\n421 too busy\\r\\n\"\n                    ),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(\n                        Y, \"250-server.example.com EHLO\\r\\n250-AUTH LOGIN PLAIN\\r\\n421 too busy\\r\\n\"\n                    ),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    receive\n                        {'DOWN', Monitor, _, _, Error} ->\n                            ?assertMatch({error, retries_exceeded, _}, Error)\n                    end,\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"retry with HELO when EHLO not accepted\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"500 5.3.3 Unrecognized command\\r\\n\"),\n                    ?assertMatch({ok, \"HELO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"use LHLO for LMTP connections\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {protocol, lmtp}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"LHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"handle single responses from DATA on LMTP connections\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {protocol, lmtp}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"LHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"handle multiple successful responses from DATA on LMTP connections\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {protocol, lmtp}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\", \"bar@foo.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"LHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<bar@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"handle mixed responses from DATA on LMTP connections #1\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {protocol, lmtp}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\", \"bar@foo.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"LHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<bar@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n452 <bar@foo.com> is temporarily over quota\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"handle mixed responses from DATA on LMTP connections #2\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}, {protocol, lmtp}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\", \"bar@foo.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 \\r\\n\"),\n                    ?assertMatch({ok, \"LHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 Some banner\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<bar@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"452 <bar@foo.com> is temporarily over quota\\r\\n\"),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"a valid complete transaction without TLS advertised should succeed\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 hostname\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"a valid complete transaction exercising period escaping\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \".hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 hostname\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"..hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"a valid complete transaction with binary arguments should succeed\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, \"testing\"}],\n                    {ok, _Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>], <<\"hello world\">>}, Options\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 hostname\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"a valid complete transaction with TLS advertised should succeed\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, <<\"testing\">>}],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch({ok, \"STARTTLS\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    application:ensure_all_started(gen_smtp),\n                    smtp_socket:send(X, \"220 ok\\r\\n\"),\n                    {ok, Y} = smtp_socket:to_ssl_server(\n                        X,\n                        [\n                            {certfile, \"test/fixtures/mx1.example.com-server.crt\"},\n                            {keyfile, \"test/fixtures/mx1.example.com-server.key\"}\n                        ],\n                        5000\n                    ),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"a valid complete transaction with TLS advertised and binary arguments should succeed\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, <<\"testing\">>}],\n                    {ok, _Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>], <<\"hello world\">>}, Options\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch({ok, \"STARTTLS\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    application:ensure_all_started(gen_smtp),\n                    smtp_socket:send(X, \"220 ok\\r\\n\"),\n                    {ok, Y} = smtp_socket:to_ssl_server(\n                        X,\n                        [\n                            {certfile, \"test/fixtures/mx1.example.com-server.crt\"},\n                            {keyfile, \"test/fixtures/mx1.example.com-server.key\"}\n                        ],\n                        5000\n                    ),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"Transaction with TLS advertised, but broken, should be restarted without TLS, if allowed\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, <<\"testing\">>},\n                        {tls, if_available}\n                    ],\n                    {ok, _Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>], <<\"hello world\">>}, Options\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch({ok, \"STARTTLS\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"220 ok\\r\\n\"),\n                    %% Now, send some invalid data instead of TLS handshake and close the socket\n                    {ok, [22, V1, V2 | _]} = smtp_socket:recv(X, 0, 1000),\n                    smtp_socket:send(X, [22, V1, V2, 0, 0]),\n                    smtp_socket:close(X),\n                    %% Client would make another attempt to connect, without TLS\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250-hostname\\r\\n250 STARTTLS\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"Send with callback\", fun() ->\n                    Options = [{relay, \"localhost\"}, {port, 9876}, {hostname, <<\"testing\">>}],\n                    Self = self(),\n                    Ref = make_ref(),\n                    Callback = fun(Arg) -> Self ! {callback, Ref, Arg} end,\n                    {ok, _Pid1} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>], <<\"hello world\">>},\n                        Options,\n                        Callback\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 hostname\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch(\n                        {ok, <<\"ok\\r\\n\">>},\n                        receive\n                            {callback, Ref, CbRet1} -> CbRet1\n                        end\n                    ),\n                    {ok, _Pid2} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>], <<\"hello world\">>},\n                        Options,\n                        Callback\n                    ),\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 hostname\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"599 error\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch(\n                        {error, send, {permanent_failure, _, <<\"599 error\\r\\n\">>}},\n                        receive\n                            {callback, Ref, CbRet2} -> CbRet2\n                        end\n                    ),\n                    ok\n                end}\n            end,\n\n            fun({ListenSock}) ->\n                {\"Deliver with RSET on transaction error\", fun() ->\n                    Self = self(),\n                    Pid = spawn_link(fun() ->\n                        EMail = {\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"},\n                        Options = [\n                            {relay, \"localhost\"},\n                            {port, 9876},\n                            {hostname, \"testing\"},\n                            {on_transaction_error, reset}\n                        ],\n                        {ok, X} = open(Options),\n                        LoopFn = fun Loop() ->\n                            receive\n                                {Self, deliver, Exp} ->\n                                    ?assertMatch({Exp, _}, deliver(X, EMail)),\n                                    Loop();\n                                {Self, stop} ->\n                                    close(X),\n                                    ok\n                            end\n                        end,\n                        LoopFn(),\n                        unlink(Self)\n                    end),\n                    {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(Y, \"220 Some Banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 hostname\\r\\n\"),\n\n                    Pid ! {self(), deliver, error},\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"RSET\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n\n                    Pid ! {self(), deliver, error},\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"RSET\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n\n                    Pid ! {self(), deliver, error},\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"RSET\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n\n                    Pid ! {self(), deliver, error},\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"354 Continue\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"599 Error\\r\\n\"),\n\n                    Pid ! {self(), deliver, ok},\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)\n                    ),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"354 Continue\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:send(Y, \"250 Ok\\r\\n\"),\n\n                    Pid ! {self(), stop},\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                    smtp_socket:close(Y),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"Deliver with QUIT on transaction error\", fun() ->\n                    Self = self(),\n                    Pid = spawn_link(fun() ->\n                        EMail = {\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"},\n                        Options = [\n                            {relay, \"localhost\"},\n                            {port, 9876},\n                            {hostname, \"testing\"},\n                            {on_transaction_error, quit}\n                        ],\n                        LoopFn = fun Loop(LastSock) ->\n                            receive\n                                {Self, deliver, Exp} ->\n                                    {ok, X} = open(Options),\n                                    ?assertMatch({Exp, _}, deliver(X, EMail)),\n                                    Loop(X);\n                                {Self, stop} ->\n                                    catch close(LastSock),\n                                    ok\n                            end\n                        end,\n                        LoopFn(undefined),\n                        unlink(Self)\n                    end),\n                    SessionInitFn = fun() ->\n                        {ok, Y} = smtp_socket:accept(ListenSock, 1000),\n                        smtp_socket:send(Y, \"220 Some Banner\\r\\n\"),\n                        ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(Y, 0, 1000)),\n                        smtp_socket:send(Y, \"250 hostname\\r\\n\"),\n                        Y\n                    end,\n\n                    Pid ! {self(), deliver, error},\n                    Y1 = SessionInitFn(),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y1, 0, 1000)\n                    ),\n                    smtp_socket:send(Y1, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y1, 0, 1000)),\n                    smtp_socket:close(Y1),\n\n                    Pid ! {self(), deliver, error},\n                    Y2 = SessionInitFn(),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y2, 0, 1000)\n                    ),\n                    smtp_socket:send(Y2, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y2, 0, 1000)),\n                    smtp_socket:send(Y2, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y2, 0, 1000)),\n                    smtp_socket:close(Y2),\n\n                    Pid ! {self(), deliver, error},\n                    Y3 = SessionInitFn(),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y3, 0, 1000)\n                    ),\n                    smtp_socket:send(Y3, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y3, 0, 1000)),\n                    smtp_socket:send(Y3, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y3, 0, 1000)),\n                    smtp_socket:send(Y3, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y3, 0, 1000)),\n                    smtp_socket:close(Y3),\n\n                    Pid ! {self(), deliver, error},\n                    Y4 = SessionInitFn(),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)\n                    ),\n                    smtp_socket:send(Y4, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)),\n                    smtp_socket:send(Y4, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)),\n                    smtp_socket:send(Y4, \"354 Continue\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)),\n                    smtp_socket:send(Y4, \"599 Error\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y4, 0, 1000)),\n                    smtp_socket:close(Y4),\n\n                    Pid ! {self(), deliver, ok},\n                    Y5 = SessionInitFn(),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)\n                    ),\n                    smtp_socket:send(Y5, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)),\n                    smtp_socket:send(Y5, \"250 Ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)),\n                    smtp_socket:send(Y5, \"354 Continue\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)),\n                    smtp_socket:send(Y5, \"250 Ok\\r\\n\"),\n\n                    Pid ! {self(), stop},\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(Y5, 0, 1000)),\n                    smtp_socket:close(Y5),\n                    ok\n                end}\n            end,\n\n            fun({ListenSock}) ->\n                {\"AUTH PLAIN should work\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, \"testing\"},\n                        {username, \"user\"},\n                        {password, \"pass\"}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH PLAIN\\r\\n\"),\n                    AuthString = binary_to_list(base64:encode(\"\\0user\\0pass\")),\n                    AuthPacket = \"AUTH PLAIN \" ++ AuthString ++ \"\\r\\n\",\n                    ?assertEqual({ok, AuthPacket}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"AUTH LOGIN should work\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, \"testing\"},\n                        {username, \"user\"},\n                        {password, \"pass\"}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH LOGIN\\r\\n\"),\n                    ?assertEqual({ok, \"AUTH LOGIN\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 VXNlcm5hbWU6\\r\\n\"),\n                    UserString = binary_to_list(base64:encode(\"user\")),\n                    ?assertEqual({ok, UserString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 UGFzc3dvcmQ6\\r\\n\"),\n                    PassString = binary_to_list(base64:encode(\"pass\")),\n                    ?assertEqual({ok, PassString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"AUTH LOGIN should work with lowercase prompts\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, \"testing\"},\n                        {username, \"user\"},\n                        {password, \"pass\"}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH LOGIN\\r\\n\"),\n                    ?assertEqual({ok, \"AUTH LOGIN\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 dXNlcm5hbWU6\\r\\n\"),\n                    UserString = binary_to_list(base64:encode(\"user\")),\n                    ?assertEqual({ok, UserString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 cGFzc3dvcmQ6\\r\\n\"),\n                    PassString = binary_to_list(base64:encode(\"pass\")),\n                    ?assertEqual({ok, PassString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"AUTH LOGIN should work with appended methods\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, \"testing\"},\n                        {username, \"user\"},\n                        {password, \"pass\"}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH LOGIN\\r\\n\"),\n                    ?assertEqual({ok, \"AUTH LOGIN\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 VXNlcm5hbWU6 R6S4yT8pcW5sQjZD3CW61N0 - hssmtp\\r\\n\"),\n                    UserString = binary_to_list(base64:encode(\"user\")),\n                    ?assertEqual({ok, UserString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"334 UGFzc3dvcmQ6 R6S4yT8pcW5sQjZD3CW61N0 - hssmtp\\r\\n\"),\n                    PassString = binary_to_list(base64:encode(\"pass\")),\n                    ?assertEqual({ok, PassString ++ \"\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"AUTH CRAM-MD5 should work\", fun() ->\n                    Options = [\n                        {relay, \"localhost\"},\n                        {port, 9876},\n                        {hostname, \"testing\"},\n                        {username, \"user\"},\n                        {password, \"pass\"}\n                    ],\n                    {ok, _Pid} = send({\"test@foo.com\", [\"foo@bar.com\"], \"hello world\"}, Options),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH CRAM-MD5\\r\\n\"),\n                    ?assertEqual({ok, \"AUTH CRAM-MD5\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    Seed = smtp_util:get_cram_string(smtp_util:guess_FQDN()),\n                    DecodedSeed = base64:decode_to_string(Seed),\n                    Digest = smtp_util:compute_cram_digest(\"pass\", DecodedSeed),\n                    String = binary_to_list(base64:encode(list_to_binary([\"user \", Digest]))),\n                    smtp_socket:send(X, \"334 \" ++ Seed ++ \"\\r\\n\"),\n                    {ok, Packet} = smtp_socket:recv(X, 0, 1000),\n                    CramDigest = smtp_util:trim_crlf(Packet),\n                    ?assertEqual(String, CramDigest),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"AUTH CRAM-MD5 should work\", fun() ->\n                    Options = [\n                        {relay, <<\"localhost\">>},\n                        {port, 9876},\n                        {hostname, <<\"testing\">>},\n                        {username, <<\"user\">>},\n                        {password, <<\"pass\">>}\n                    ],\n                    {ok, _Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>, <<\"baz@bar.com\">>], <<\"hello world\">>},\n                        Options\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH CRAM-MD5\\r\\n\"),\n                    ?assertEqual({ok, \"AUTH CRAM-MD5\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    Seed = smtp_util:get_cram_string(smtp_util:guess_FQDN()),\n                    DecodedSeed = base64:decode_to_string(Seed),\n                    Digest = smtp_util:compute_cram_digest(\"pass\", DecodedSeed),\n                    String = binary_to_list(base64:encode(list_to_binary([\"user \", Digest]))),\n                    smtp_socket:send(X, \"334 \" ++ Seed ++ \"\\r\\n\"),\n                    {ok, Packet} = smtp_socket:recv(X, 0, 1000),\n                    CramDigest = smtp_util:trim_crlf(Packet),\n                    ?assertEqual(String, CramDigest),\n                    smtp_socket:send(X, \"235 ok\\r\\n\"),\n                    ?assertMatch(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"should bail when AUTH is required but not provided\", fun() ->\n                    Options = [\n                        {relay, <<\"localhost\">>},\n                        {port, 9876},\n                        {hostname, <<\"testing\">>},\n                        {auth, always},\n                        {username, <<\"user\">>},\n                        {retries, 0},\n                        {password, <<\"pass\">>}\n                    ],\n                    {ok, Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>, <<\"baz@bar.com\">>], <<\"hello world\">>},\n                        Options\n                    ),\n                    unlink(Pid),\n                    Monitor = erlang:monitor(process, Pid),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 8BITMIME\\r\\n\"),\n                    ?assertEqual({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    receive\n                        {'DOWN', Monitor, _, _, Error} ->\n                            ?assertMatch(\n                                {error, retries_exceeded, {missing_requirement, _, auth}}, Error\n                            )\n                    end,\n                    ok\n                end}\n            end,\n            fun({ListenSock}) ->\n                {\"should bail when AUTH is required but of an unsupported type\", fun() ->\n                    Options = [\n                        {relay, <<\"localhost\">>},\n                        {port, 9876},\n                        {hostname, <<\"testing\">>},\n                        {auth, always},\n                        {username, <<\"user\">>},\n                        {retries, 0},\n                        {password, <<\"pass\">>}\n                    ],\n                    {ok, Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"foo@bar.com\">>, <<\"baz@bar.com\">>], <<\"hello world\">>},\n                        Options\n                    ),\n                    unlink(Pid),\n                    Monitor = erlang:monitor(process, Pid),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250-AUTH GSSAPI\\r\\n250 8BITMIME\\r\\n\"),\n                    ?assertEqual({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    receive\n                        {'DOWN', Monitor, _, _, Error} ->\n                            ?assertMatch(\n                                {error, no_more_hosts, {permanent_failure, _, auth_failed}}, Error\n                            )\n                    end,\n                    ok\n                end}\n            end,\n            fun({_ListenSock}) ->\n                {\"Connecting to a SSL socket directly should work\", fun() ->\n                    application:ensure_all_started(gen_smtp),\n                    {ok, ListenSock} = smtp_socket:listen(ssl, 9877, [\n                        {certfile, \"test/fixtures/mx1.example.com-server.crt\"},\n                        {keyfile, \"test/fixtures/mx1.example.com-server.key\"}\n                    ]),\n                    Options = [\n                        {relay, <<\"localhost\">>},\n                        {port, 9877},\n                        {hostname, <<\"testing\">>},\n                        {ssl, true}\n                    ],\n                    {ok, _Pid} = send(\n                        {<<\"test@foo.com\">>, [<<\"<foo@bar.com>\">>, <<\"baz@bar.com\">>], <<\"hello world\">>},\n                        Options\n                    ),\n                    {ok, X} = smtp_socket:accept(ListenSock, 1000),\n                    smtp_socket:send(X, \"220 Some banner\\r\\n\"),\n                    ?assertMatch({ok, \"EHLO testing\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250-hostname\\r\\n250 AUTH CRAM-MD5\\r\\n\"),\n                    ?assertEqual(\n                        {ok, \"MAIL FROM:<test@foo.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)\n                    ),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<foo@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"RCPT TO:<baz@bar.com>\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"DATA\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"354 ok\\r\\n\"),\n                    ?assertMatch({ok, \"hello world\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    ?assertMatch({ok, \".\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:send(X, \"250 ok\\r\\n\"),\n                    ?assertMatch({ok, \"QUIT\\r\\n\"}, smtp_socket:recv(X, 0, 1000)),\n                    smtp_socket:close(ListenSock),\n                    ok\n                end}\n            end\n        ]}.\n\nextension_parse_test_() ->\n    [\n        {\"parse extensions\", fun() ->\n            Res = parse_extensions(\n                <<\"250-smtp.example.com\\r\\n250-PIPELINING\\r\\n250-SIZE 20971520\\r\\n250-VRFY\\r\\n250-ETRN\\r\\n250-STARTTLS\\r\\n250-AUTH CRAM-MD5 PLAIN DIGEST-MD5 LOGIN\\r\\n250-AUTH=CRAM-MD5 PLAIN DIGEST-MD5 LOGIN\\r\\n250-ENHANCEDSTATUSCODES\\r\\n250-8BITMIME\\r\\n250 DSN\">>,\n                []\n            ),\n            ?assertEqual(true, proplists:get_value(<<\"PIPELINING\">>, Res)),\n            ?assertEqual(<<\"20971520\">>, proplists:get_value(<<\"SIZE\">>, Res)),\n            ?assertEqual(true, proplists:get_value(<<\"VRFY\">>, Res)),\n            ?assertEqual(true, proplists:get_value(<<\"ETRN\">>, Res)),\n            ?assertEqual(true, proplists:get_value(<<\"STARTTLS\">>, Res)),\n            ?assertEqual(\n                <<\"CRAM-MD5 PLAIN DIGEST-MD5 LOGIN\">>, proplists:get_value(<<\"AUTH\">>, Res)\n            ),\n            ?assertEqual(true, proplists:get_value(<<\"ENHANCEDSTATUSCODES\">>, Res)),\n            ?assertEqual(true, proplists:get_value(<<\"8BITMIME\">>, Res)),\n            ?assertEqual(true, proplists:get_value(<<\"DSN\">>, Res)),\n            ?assertEqual(10, length(Res)),\n            ok\n        end}\n    ].\n\n-endif.\n"
  },
  {
    "path": "src/gen_smtp_server.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc Setup ranch socket acceptor for gen_smtp_server_session\n\n-module(gen_smtp_server).\n\n-define(PORT, 2525).\n\n-include_lib(\"kernel/include/logger.hrl\").\n\n%% External API\n-export([\n    start/3, start/2, start/1,\n    stop/1,\n    child_spec/3,\n    sessions/1\n]).\n-export_type([options/0]).\n\n-type server_name() :: any().\n-type options() ::\n    [\n        {domain, string()}\n        | {address, inet:ip4_address()}\n        | {family, inet | inet6}\n        | {port, inet:port_number()}\n        | {protocol, 'tcp' | 'ssl'}\n        | {ranch_opts, ranch:opts()}\n        | {sessionoptions, gen_smtp_server_session:options()}\n    ].\n\n%% @doc Start the listener as a registered process with callback module `Module' with options `Options' linked to no process.\n-spec start(\n    ServerName :: server_name(),\n    CallbackModule :: module(),\n    Options :: options()\n) -> {'ok', pid()} | {'error', any()}.\nstart(ServerName, CallbackModule, Options) when is_list(Options) ->\n    case convert_options(CallbackModule, Options) of\n        {ok, Transport, TransportOpts, ProtocolOpts} ->\n            ranch:start_listener(\n                ServerName, Transport, TransportOpts, gen_smtp_server_session, ProtocolOpts\n            );\n        {error, Reason} ->\n            {error, Reason}\n    end.\n\nchild_spec(ServerName, CallbackModule, Options) ->\n    case convert_options(CallbackModule, Options) of\n        {ok, Transport, TransportOpts, ProtocolOpts} ->\n            ranch:child_spec(\n                ServerName, Transport, TransportOpts, gen_smtp_server_session, ProtocolOpts\n            );\n        {error, Reason} ->\n            % `supervisor:child_spec' is not compatible with ok/error tuples.\n            % This error is likely to occur when starting the application,\n            % so the user can sort out the configuration parameters and try again.\n            erlang:error(Reason)\n    end.\n\nconvert_options(CallbackModule, Options) ->\n    Transport =\n        case proplists:get_value(protocol, Options, tcp) of\n            tcp -> ranch_tcp;\n            ssl -> ranch_ssl\n        end,\n    Family = proplists:get_value(family, Options, inet),\n    Address = proplists:get_value(address, Options, {0, 0, 0, 0}),\n    Port = proplists:get_value(port, Options, ?PORT),\n    Hostname = proplists:get_value(domain, Options, smtp_util:guess_FQDN()),\n    ProtocolOpts = proplists:get_value(sessionoptions, Options, []),\n    EmailTransferProtocol = proplists:get_value(protocol, ProtocolOpts, smtp),\n    case {EmailTransferProtocol, Port} of\n        {lmtp, 25} ->\n            ?LOG_ERROR(\"LMTP is different from SMTP, it MUST NOT be used on the TCP port 25\", #{\n                domain => [gen_smtp, server]\n            }),\n            % Error defined in section 5 of https://tools.ietf.org/html/rfc2033\n            {error, invalid_lmtp_port};\n        _ ->\n            ProtocolOpts1 = {CallbackModule, [{hostname, Hostname} | ProtocolOpts]},\n            RanchOpts = proplists:get_value(ranch_opts, Options, #{}),\n            SocketOpts = maps:get(socket_opts, RanchOpts, []),\n            TransportOpts = RanchOpts#{\n                socket_opts =>\n                    [\n                        {port, Port},\n                        {ip, Address},\n                        {keepalive, true},\n                        %% binary, {active, false}, {reuseaddr, true} - ranch defaults\n                        Family\n                        | SocketOpts\n                    ]\n            },\n            {ok, Transport, TransportOpts, ProtocolOpts1}\n    end.\n\n%% @doc Start the listener with callback module `Module' with options `Options' linked to no process.\n-spec start(CallbackModule :: module(), Options :: options()) ->\n    {'ok', pid()} | 'ignore' | {'error', any()}.\nstart(CallbackModule, Options) when is_list(Options) ->\n    start(?MODULE, CallbackModule, Options).\n\n%% @doc Start the listener with callback module `Module' with default options linked to no process.\n-spec start(CallbackModule :: atom()) -> {'ok', pid()} | 'ignore' | {'error', any()}.\nstart(CallbackModule) ->\n    start(CallbackModule, []).\n\n%% @doc Stop the listener pid() `Pid' with reason `normal'.\n-spec stop(Name :: server_name()) -> 'ok'.\nstop(Name) ->\n    ranch:stop_listener(Name).\n\n%% @doc Return the list of active SMTP session pids.\n-spec sessions(Name :: server_name()) -> [pid()].\nsessions(Name) ->\n    ranch:procs(Name, connections).\n"
  },
  {
    "path": "src/gen_smtp_server_session.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc Process representing a SMTP session, extensible via a callback module. This\n%% module is implemented as a behaviour that the callback module should\n%% implement. To see the details of the required callback functions to provide,\n%% please see `smtp_server_example'.\n%% @see smtp_server_example\n\n-module(gen_smtp_server_session).\n-behaviour(gen_server).\n-behaviour(ranch_protocol).\n\n-ifdef(TEST).\n-include_lib(\"eunit/include/eunit.hrl\").\n-endif.\n\n%10mb\n-define(DEFAULT_MAXSIZE, 10485760).\n-define(BUILTIN_EXTENSIONS, [\n    {\"SIZE\", integer_to_list(?DEFAULT_MAXSIZE)},\n    {\"8BITMIME\", true},\n    {\"PIPELINING\", true},\n    {\"SMTPUTF8\", true}\n]).\n% 3 minutes\n-define(TIMEOUT, 180000).\n\n%% External API\n-export([start_link/3, start_link/4]).\n-export([ranch_init/1]).\n\n%% gen_server callbacks\n-export([\n    init/1,\n    handle_call/3,\n    handle_cast/2,\n    handle_info/2,\n    terminate/2,\n    code_change/3\n]).\n-export_type([options/0, error_class/0, protocol_message/0]).\n\n-include_lib(\"kernel/include/logger.hrl\").\n-define(LOGGER_META, #{domain => [gen_smtp, server]}).\n\n-record(envelope, {\n    from :: binary() | 'undefined',\n    to = [] :: [binary()],\n    data = <<>> :: binary(),\n    expectedsize = 0 :: pos_integer() | 0,\n    % {\"username\", \"password\"}\n    auth = {<<>>, <<>>} :: {binary(), binary()},\n    flags = [] :: [smtputf8 | '8bitmime' | '7bit']\n}).\n\n-record(state, {\n    socket = erlang:error({undefined, socket}) :: port() | tuple(),\n    module = erlang:error({undefined, module}) :: atom(),\n    transport :: module(),\n    ranch_ref :: ranch:ref(),\n    envelope = undefined :: 'undefined' | #envelope{},\n    extensions = [] :: [{string(), string()}],\n    maxsize = ?DEFAULT_MAXSIZE :: pos_integer() | 'infinity',\n    waitingauth = false :: 'false' | 'plain' | 'login' | 'cram-md5',\n    authdata :: 'undefined' | binary(),\n    readmessage = false :: boolean(),\n    tls = false :: boolean(),\n    callbackstate :: any(),\n    protocol = smtp :: 'smtp' | 'lmtp',\n    options = [] :: [tuple()]\n}).\n\n-type tls_opt() :: ssl:tls_server_option().\n\n-type options() :: [\n    {callbackoptions, any()}\n    % deprecated, see tls_options\n    | {certfile, file:name_all()}\n    % deprecated, see tls_options\n    | {keyfile, file:name_all()}\n    | {allow_bare_newlines, false | ignore | fix | strip}\n    | {hostname, inet:hostname()}\n    | {protocol, smtp | lmtp}\n    | {tls_options, [tls_opt()]}\n].\n\n-type state() :: any().\n-type error_message() :: {error, string(), state()}.\n-type error_class() ::\n    tcp_closed\n    | tcp_error\n    | ssl_closed\n    | ssl_error\n    | data_rejected\n    | timeout\n    | out_of_order\n    | ssl_handshake_error\n    | send_error\n    | setopts_error\n    | data_receive_error.\n\n-type protocol_message() :: string() | iodata().\n\n-callback init(\n    Hostname :: inet:hostname(),\n    _SessionCount,\n    Peername :: inet:ip_address(),\n    Opts :: any()\n) ->\n    {ok, Banner :: iodata(), CallbackState :: state()}\n    | {stop, Reason :: any(), Message :: iodata()}\n    | ignore.\n-callback code_change(OldVsn :: any(), State :: state(), Extra :: any()) -> {ok, state()}.\n-callback handle_HELO(Hostname :: binary(), State :: state()) ->\n    {ok, pos_integer() | 'infinity', state()} | {ok, state()} | error_message().\n-callback handle_EHLO(Hostname :: binary(), Extensions :: list(), State :: state()) ->\n    {ok, list(), state()} | error_message().\n-callback handle_STARTTLS(state()) -> state().\n-callback handle_AUTH(\n    AuthType :: login | plain | 'cram-md5',\n    Username :: binary(),\n    Credential :: binary() | {binary(), binary()},\n    State :: state()\n) ->\n    {ok, state()} | any().\n-callback handle_MAIL(From :: binary(), State :: state()) ->\n    {ok, state()} | {error, string(), state()}.\n-callback handle_MAIL_extension(Extension :: binary(), State :: state()) ->\n    {ok, state()} | error.\n-callback handle_RCPT(To :: binary(), State :: state()) ->\n    {ok, state()} | {error, string(), state()}.\n-callback handle_RCPT_extension(Extension :: binary(), State :: state()) ->\n    {ok, state()} | error.\n-callback handle_DATA(From :: binary(), To :: [binary(), ...], Data :: binary(), State :: state()) ->\n    {ok | error, protocol_message(), state()}\n    | {multiple, [{ok | error, protocol_message()}], state()}.\n% the 'multiple' reply is only available for LMTP\n-callback handle_RSET(State :: state()) -> state().\n-callback handle_VRFY(Address :: binary(), State :: state()) ->\n    {ok, string(), state()} | {error, string(), state()}.\n-callback handle_other(Verb :: binary(), Args :: binary(), state()) ->\n    {string() | noreply, state()}.\n-callback handle_info(Info :: term(), State :: state()) ->\n    {noreply, NewState :: state()}\n    | {noreply, NewState :: state(), timeout() | hibernate}\n    | {stop, Reason :: term(), NewState :: term()}.\n-callback handle_error(error_class(), any(), state()) ->\n    {ok, state()} | {stop, Reason :: any(), state()}.\n-callback terminate(Reason :: any(), state()) -> {ok, Reason :: any(), state()}.\n\n-optional_callbacks([handle_info/2, handle_AUTH/4, handle_error/3]).\n\n%% @doc Start a SMTP session linked to the calling process.\n-spec start_link(\n    Ref :: ranch:ref(),\n    Transport :: module(),\n    {Callback :: module(), Options :: options()}\n) ->\n    {'ok', pid()}.\nstart_link(Ref, Transport, Options) ->\n    {ok, proc_lib:spawn_link(?MODULE, ranch_init, [{Ref, Transport, Options}])}.\n\nstart_link(Ref, _Sock, Transport, Options) ->\n    start_link(Ref, Transport, Options).\n\nranch_init({Ref, Transport, {Callback, Opts}}) ->\n    {ok, Socket} = ranch:handshake(Ref),\n    case init([Ref, Transport, Socket, Callback, Opts]) of\n        {ok, State, Timeout} ->\n            gen_server:enter_loop(?MODULE, [], State, Timeout);\n        {stop, Reason} ->\n            exit(Reason);\n        ignore ->\n            ok\n    end.\n\n%% @private\n-spec init(Args :: list()) -> {'ok', #state{}, ?TIMEOUT} | {'stop', any()} | 'ignore'.\ninit([Ref, Transport, Socket, Module, Options]) ->\n    Protocol = proplists:get_value(protocol, Options, smtp),\n    PeerName =\n        case Transport:peername(Socket) of\n            {ok, {IPaddr, _Port}} -> IPaddr;\n            {error, _} -> error\n        end,\n    case\n        PeerName =/= error andalso\n            Module:init(\n                hostname(Options),\n                %FIXME\n                proplists:get_value(sessioncount, Options, 0),\n                PeerName,\n                proplists:get_value(callbackoptions, Options, [])\n            )\n    of\n        false ->\n            Transport:close(Socket),\n            ignore;\n        {ok, Banner, CallbackState} ->\n            Transport:send(Socket, [\"220 \", Banner, \"\\r\\n\"]),\n            ok = Transport:setopts(Socket, [\n                {active, once},\n                {packet, line},\n                binary\n            ]),\n            {ok,\n                #state{\n                    socket = Socket,\n                    transport = Transport,\n                    module = Module,\n                    ranch_ref = Ref,\n                    protocol = Protocol,\n                    options = Options,\n                    callbackstate = CallbackState\n                },\n                ?TIMEOUT};\n        {stop, Reason, Message} ->\n            Transport:send(Socket, [Message, \"\\r\\n\"]),\n            Transport:close(Socket),\n            {stop, Reason};\n        ignore ->\n            Transport:close(Socket),\n            ignore\n    end.\n\n%% @hidden\nhandle_call(stop, _From, State) ->\n    {stop, normal, ok, State};\nhandle_call(Request, _From, State) ->\n    {reply, {unknown_call, Request}, State}.\n\n%% @hidden\nhandle_cast(_Msg, State) ->\n    {noreply, State}.\n\n%% @hidden\n-spec handle_info(Message :: any(), State :: #state{}) ->\n    {'noreply', #state{}} | {'stop', any(), #state{}}.\nhandle_info({receive_data, {error, size_exceeded}}, #state{readmessage = true} = State) ->\n    send(State, \"552 Message too large\\r\\n\"),\n    setopts(State, [{active, once}]),\n    State1 = handle_error(data_rejected, size_exceeded, State),\n    {noreply, State1#state{readmessage = false, envelope = #envelope{}}, ?TIMEOUT};\nhandle_info({receive_data, {error, bare_newline}}, #state{readmessage = true} = State) ->\n    send(State, \"451 Bare newline detected\\r\\n\"),\n    setopts(State, [{active, once}]),\n    State1 = handle_error(data_rejected, bare_neline, State),\n    {noreply, State1#state{readmessage = false, envelope = #envelope{}}, ?TIMEOUT};\nhandle_info({receive_data, {error, Other}}, #state{readmessage = true} = State) ->\n    State1 = handle_error(data_receive_error, Other, State),\n    {stop, {error_receiving_data, Other}, State1};\nhandle_info(\n    {receive_data, Body, Rest},\n    #state{\n        socket = Socket,\n        transport = Transport,\n        readmessage = true,\n        envelope = Env,\n        module = Module,\n        callbackstate = OldCallbackState,\n        maxsize = MaxSize\n    } = State\n) ->\n    % send the remainder of the data...\n    case Rest of\n        % no remaining data\n        <<>> -> ok;\n        _ -> self() ! {Transport:name(), Socket, Rest}\n    end,\n    setopts(State, [{packet, line}]),\n    %% Unescape periods at start of line (rfc5321 4.5.2)\n    Data = re:replace(Body, <<\"^\\\\\\.\">>, <<>>, [global, multiline, {return, binary}]),\n    #envelope{from = From, to = To} = Env,\n    case MaxSize =:= infinity orelse byte_size(Data) =< MaxSize of\n        true ->\n            {ResponseType, Value, CallbackState} = Module:handle_DATA(\n                From, To, Data, OldCallbackState\n            ),\n            report_recipient(ResponseType, Value, State),\n            setopts(State, [{active, once}]),\n            {noreply,\n                State#state{\n                    readmessage = false,\n                    envelope = #envelope{},\n                    callbackstate = CallbackState\n                },\n                ?TIMEOUT};\n        false ->\n            send(State, \"552 Message too large\\r\\n\"),\n            setopts(State, [{active, once}]),\n            % might not even be able to get here anymore...\n            {noreply, State#state{readmessage = false, envelope = #envelope{}}, ?TIMEOUT}\n    end;\nhandle_info(\n    {SocketType, Socket, Packet},\n    #state{socket = Socket, transport = Transport, waitingauth = false} = State\n) when\n    SocketType =:= tcp; SocketType =:= ssl\n->\n    case handle_request(parse_request(Packet), State) of\n        {ok, #state{options = Options, readmessage = true, maxsize = MaxSize} = NewState} ->\n            Session = self(),\n            Size = 0,\n            setopts(NewState, [{packet, raw}]),\n            %% TODO: change to receive asynchronously in the same process\n            spawn_opt(\n                fun() ->\n                    receive_data([], Transport, Socket, 0, Size, MaxSize, Session, Options)\n                end,\n                [link, {fullsweep_after, 0}]\n            ),\n            {noreply, NewState, ?TIMEOUT};\n        {ok, NewState} ->\n            setopts(NewState, [{active, once}]),\n            {noreply, NewState, ?TIMEOUT};\n        {stop, Reason, NewState} ->\n            {stop, Reason, NewState}\n    end;\nhandle_info({SocketType, Socket, Packet}, #state{socket = Socket} = State) when\n    SocketType =:= tcp; SocketType =:= ssl\n->\n    %% We are in SASL state RFC-4954\n    Request = binstr:strip(\n        binstr:strip(binstr:strip(binstr:strip(Packet, right, $\\n), right, $\\r), right, $\\s),\n        left,\n        $\\s\n    ),\n    ?LOG_DEBUG(\"Got SASL request ~p\", [Request], ?LOGGER_META),\n    {ok, NewState} = handle_sasl(base64:decode(Request), State),\n    setopts(NewState, [{active, once}]),\n    {noreply, NewState, ?TIMEOUT};\nhandle_info({Kind, _Socket}, State) when\n    Kind == tcp_closed;\n    Kind == ssl_closed\n->\n    State1 = handle_error(Kind, [], State),\n    {stop, normal, State1};\nhandle_info({Kind, _Socket, Reason}, State) when\n    Kind == ssl_error;\n    Kind == tcp_error\n->\n    State1 = handle_error(Kind, Reason, State),\n    {stop, normal, State1};\nhandle_info(timeout, #state{socket = Socket, transport = Transport} = State) ->\n    send(State, \"421 Error: timeout exceeded\\r\\n\"),\n    Transport:close(Socket),\n    State1 = handle_error(timeout, [], State),\n    {stop, normal, State1};\nhandle_info(Info, #state{module = Module, callbackstate = OldCallbackState} = State) ->\n    case erlang:function_exported(Module, handle_info, 2) of\n        true ->\n            case Module:handle_info(Info, OldCallbackState) of\n                {noreply, NewCallbackState} ->\n                    {noreply, State#state{callbackstate = NewCallbackState}};\n                {noreply, NewCallbackState, Action} ->\n                    {noreply, State#state{callbackstate = NewCallbackState}, Action};\n                {stop, Reason, NewCallbackState} ->\n                    {stop, Reason, State#state{callbackstate = NewCallbackState}}\n            end;\n        false ->\n            ?LOG_DEBUG(\"Ignored message ~p\", [Info], ?LOGGER_META),\n            {noreply, State, ?TIMEOUT}\n    end.\n\n%% @hidden\n-spec terminate(Reason :: any(), State :: #state{}) -> 'ok'.\nterminate(Reason, #state{\n    socket = Socket,\n    transport = Transport,\n    module = Module,\n    callbackstate = CallbackState\n}) ->\n    ok = Transport:close(Socket),\n    Module:terminate(Reason, CallbackState).\n\n%% @hidden\n-spec code_change(OldVsn :: any(), State :: #state{}, Extra :: any()) -> {'ok', #state{}}.\ncode_change(OldVsn, #state{module = Module, callbackstate = CallbackState} = State, Extra) ->\n    % TODO - this should probably be the callback module's version or its checksum\n    CallbackState =\n        case catch Module:code_change(OldVsn, CallbackState, Extra) of\n            {ok, NewCallbackState} -> NewCallbackState;\n            _ -> CallbackState\n        end,\n    {ok, State#state{callbackstate = CallbackState}}.\n\n-spec parse_request(Packet :: binary()) -> {binary(), binary()}.\nparse_request(Packet) ->\n    Request = binstr:strip(\n        binstr:strip(binstr:strip(binstr:strip(Packet, right, $\\n), right, $\\r), right, $\\s),\n        left,\n        $\\s\n    ),\n    case binstr:strchr(Request, $\\s) of\n        0 ->\n            ?LOG_DEBUG(\"got a ~s request\", [Request], ?LOGGER_META),\n            {binstr:to_upper(Request), <<>>};\n        Index ->\n            Verb = binstr:substr(Request, 1, Index - 1),\n            Parameters = binstr:strip(binstr:substr(Request, Index + 1), left, $\\s),\n            ?LOG_DEBUG(\"got a ~s request with parameters ~s\", [Verb, Parameters], ?LOGGER_META),\n            {binstr:to_upper(Verb), Parameters}\n    end.\n\n-spec handle_request({Verb :: binary(), Args :: binary()}, State :: #state{}) ->\n    {'ok', #state{}} | {'stop', any(), #state{}}.\nhandle_request({<<>>, _Any}, State) ->\n    send(State, \"500 Error: bad syntax\\r\\n\"),\n    {ok, State};\nhandle_request({Command, <<>>}, State) when\n    Command == <<\"HELO\">>; Command == <<\"EHLO\">>; Command == <<\"LHLO\">>\n->\n    send(State, [\"501 Syntax: \", Command, \" hostname\\r\\n\"]),\n    {ok, State};\nhandle_request({<<\"LHLO\">>, _Any}, #state{protocol = smtp} = State) ->\n    send(State, \"500 Error: SMTP should send HELO or EHLO instead of LHLO\\r\\n\"),\n    {ok, State};\nhandle_request({Msg, _Any}, #state{protocol = lmtp} = State) when\n    Msg == <<\"HELO\">>; Msg == <<\"EHLO\">>\n->\n    send(State, \"500 Error: LMTP should replace HELO and EHLO with LHLO\\r\\n\"),\n    {ok, State};\nhandle_request(\n    {<<\"HELO\">>, Hostname},\n    #state{options = Options, module = Module, callbackstate = OldCallbackState} = State\n) ->\n    case Module:handle_HELO(Hostname, OldCallbackState) of\n        {ok, MaxSize, CallbackState} when MaxSize =:= infinity; is_integer(MaxSize) ->\n            Data = [\"250 \", hostname(Options), \"\\r\\n\"],\n            send(State, Data),\n            {ok, State#state{\n                maxsize = MaxSize,\n                envelope = #envelope{},\n                callbackstate = CallbackState\n            }};\n        {ok, CallbackState} ->\n            Data = [\"250 \", hostname(Options), \"\\r\\n\"],\n            send(State, Data),\n            {ok, State#state{envelope = #envelope{}, callbackstate = CallbackState}};\n        {error, Message, CallbackState} ->\n            send(State, [Message, \"\\r\\n\"]),\n            {ok, State#state{callbackstate = CallbackState}}\n    end;\nhandle_request(\n    {Msg, Hostname},\n    #state{options = Options, module = Module, callbackstate = OldCallbackState, tls = Tls} = State\n) when\n    Msg == <<\"EHLO\">>; Msg == <<\"LHLO\">>\n->\n    case Module:handle_EHLO(Hostname, ?BUILTIN_EXTENSIONS, OldCallbackState) of\n        {ok, [], CallbackState} ->\n            Data = [\"250 \", hostname(Options), \"\\r\\n\"],\n            send(State, Data),\n            {ok, State#state{extensions = [], callbackstate = CallbackState}};\n        {ok, Extensions, CallbackState} ->\n            ExtensionsUpper = lists:map(fun({X, Y}) -> {string:to_upper(X), Y} end, Extensions),\n            {Extensions1, MaxSize} =\n                case lists:keyfind(\"SIZE\", 1, ExtensionsUpper) of\n                    {\"SIZE\", \"0\"} ->\n                        {lists:keydelete(\"SIZE\", 1, ExtensionsUpper), infinity};\n                    {\"SIZE\", MaxSizeString} when is_list(MaxSizeString) ->\n                        {ExtensionsUpper, list_to_integer(MaxSizeString)};\n                    false ->\n                        {ExtensionsUpper, State#state.maxsize}\n                end,\n            Extensions2 =\n                case Tls of\n                    true ->\n                        lists:delete({\"STARTTLS\", true}, Extensions1);\n                    false ->\n                        Extensions1\n                end,\n            Response = (fun\n                F([{E, true}]) -> [\"250 \", E, \"\\r\\n\"];\n                F([{E, V}]) -> [\"250 \", E, \" \", V, \"\\r\\n\"];\n                F([Line]) -> [\"250 \", Line, \"\\r\\n\"];\n                F([{E, true} | More]) -> [\"250-\", E, \"\\r\\n\" | F(More)];\n                F([{E, V} | More]) -> [\"250-\", E, \" \", V, \"\\r\\n\" | F(More)];\n                F([Line | More]) -> [\"250-\", Line, \"\\r\\n\" | F(More)]\n            end)(\n                [hostname(Options) | Extensions2]\n            ),\n            %?debugFmt(\"Respponse ~p~n\", [lists:reverse(Response)]),\n            send(State, Response),\n            {ok, State#state{\n                extensions = Extensions2,\n                maxsize = MaxSize,\n                envelope = #envelope{},\n                callbackstate = CallbackState\n            }};\n        {error, Message, CallbackState} ->\n            send(State, [Message, \"\\r\\n\"]),\n            {ok, State#state{callbackstate = CallbackState}}\n    end;\nhandle_request({<<\"AUTH\">> = C, _Args}, #state{envelope = undefined, protocol = Protocol} = State) ->\n    send(State, [\"503 Error: send \", lhlo_if_lmtp(Protocol, \"EHLO\"), \" first\\r\\n\"]),\n    State1 = handle_error(out_of_order, C, State),\n    {ok, State1};\nhandle_request(\n    {<<\"AUTH\">>, Args},\n    #state{extensions = Extensions, envelope = Envelope, options = Options} = State\n) ->\n    case binstr:strchr(Args, $\\s) of\n        0 ->\n            AuthType = Args,\n            Parameters = false;\n        Index ->\n            AuthType = binstr:substr(Args, 1, Index - 1),\n            Parameters = binstr:strip(binstr:substr(Args, Index + 1), left, $\\s)\n    end,\n\n    case has_extension(Extensions, \"AUTH\") of\n        false ->\n            send(State, \"502 Error: AUTH not implemented\\r\\n\"),\n            {ok, State};\n        {true, AvailableTypes} ->\n            case\n                lists:member(\n                    string:to_upper(binary_to_list(AuthType)),\n                    string:tokens(AvailableTypes, \" \")\n                )\n            of\n                false ->\n                    send(State, \"504 Unrecognized authentication type\\r\\n\"),\n                    {ok, State};\n                true ->\n                    case binstr:to_upper(AuthType) of\n                        <<\"LOGIN\">> ->\n                            % smtp_socket:send(Socket, \"334 \" ++ base64:encode_to_string(\"Username:\")),\n                            send(State, \"334 VXNlcm5hbWU6\\r\\n\"),\n                            {ok, State#state{\n                                waitingauth = 'login',\n                                envelope = Envelope#envelope{auth = {<<>>, <<>>}}\n                            }};\n                        <<\"PLAIN\">> when Parameters =/= false ->\n                            % TODO - duplicated below in handle_request waitingauth PLAIN\n                            case binstr:split(base64:decode(Parameters), <<0>>) of\n                                [_Identity, Username, Password] ->\n                                    try_auth('plain', Username, Password, State);\n                                [Username, Password] ->\n                                    try_auth('plain', Username, Password, State);\n                                _ ->\n                                    % TODO error\n                                    {ok, State}\n                            end;\n                        <<\"PLAIN\">> ->\n                            send(State, \"334\\r\\n\"),\n                            {ok, State#state{\n                                waitingauth = 'plain',\n                                envelope = Envelope#envelope{auth = {<<>>, <<>>}}\n                            }};\n                        <<\"CRAM-MD5\">> ->\n                            % ensure crypto is started, we're gonna need it\n                            application:ensure_started(crypto),\n                            String = smtp_util:get_cram_string(hostname(Options)),\n                            send(State, [\"334 \", String, \"\\r\\n\"]),\n                            {ok, State#state{\n                                waitingauth = 'cram-md5',\n                                authdata = base64:decode(String),\n                                envelope = Envelope#envelope{auth = {<<>>, <<>>}}\n                            }}\n                        %\"DIGEST-MD5\" -> % TODO finish this? (see rfc 2831)\n                        %crypto:start(), % ensure crypto is started, we're gonna need it\n                        %Nonce = get_digest_nonce(),\n                        %Response = io_lib:format(\"nonce=\\\"~s\\\",realm=\\\"~s\\\",qop=\\\"auth\\\",algorithm=md5-sess,charset=utf-8\", Nonce, State#state.hostname),\n                        %smtp_socket:send(Socket, \"334 \"++Response++\"\\r\\n\"),\n                        %{ok, State#state{waitingauth = \"DIGEST-MD5\", authdata=base64:decode_to_string(Nonce), envelope = Envelope#envelope{auth = {[], []}}}}\n                    end\n            end\n    end;\nhandle_request({<<\"MAIL\">> = C, _Args}, #state{envelope = undefined, protocol = Protocol} = State) ->\n    send(State, [\"503 Error: send \", lhlo_if_lmtp(Protocol, \"HELO/EHLO\"), \" first\\r\\n\"]),\n    State1 = handle_error(out_of_order, C, State),\n    {ok, State1};\nhandle_request(\n    {<<\"MAIL\">>, Args},\n    #state{\n        module = Module,\n        envelope = Envelope0,\n        callbackstate = OldCallbackState,\n        extensions = Extensions,\n        maxsize = MaxSize\n    } = State\n) ->\n    case Envelope0#envelope.from of\n        undefined ->\n            case binstr:strpos(binstr:to_upper(Args), <<\"FROM:\">>) of\n                1 ->\n                    Address = binstr:strip(binstr:substr(Args, 6), left, $\\s),\n                    case\n                        parse_encoded_address(\n                            Address, has_extension(Extensions, \"SMTPUTF8\") =/= false\n                        )\n                    of\n                        error ->\n                            send(State, \"501 Bad sender address syntax\\r\\n\"),\n                            {ok, State};\n                        {ParsedAddress, <<>>} ->\n                            ?LOG_DEBUG(\"From address ~s (parsed as ~s)\", [Address, ParsedAddress], ?LOGGER_META),\n                            case Module:handle_MAIL(ParsedAddress, OldCallbackState) of\n                                {ok, CallbackState} ->\n                                    send(State, \"250 sender Ok\\r\\n\"),\n                                    {ok, State#state{\n                                        envelope = Envelope0#envelope{from = ParsedAddress},\n                                        callbackstate = CallbackState\n                                    }};\n                                {error, Message, CallbackState} ->\n                                    send(State, [Message, \"\\r\\n\"]),\n                                    {ok, State#state{callbackstate = CallbackState}}\n                            end;\n                        {ParsedAddress, ExtraInfo} ->\n                            ?LOG_DEBUG(\n                                \"From address ~s (parsed as ~s) with extra info ~s\",\n                                [\n                                    Address, ParsedAddress, ExtraInfo\n                                ],\n                                ?LOGGER_META\n                            ),\n                            Options = [binstr:to_upper(X) || X <- binstr:split(ExtraInfo, <<\" \">>)],\n                            ?LOG_DEBUG(\"options are ~p\", [Options], ?LOGGER_META),\n                            F = fun\n                                (_, {error, Message}) ->\n                                    {error, Message};\n                                (\n                                    <<\"SIZE=\", Size/binary>>,\n                                    #state{envelope = Envelope} = InnerState\n                                ) when MaxSize =:= 'infinity' ->\n                                    InnerState#state{\n                                        envelope = Envelope#envelope{\n                                            expectedsize = binary_to_integer(Size)\n                                        }\n                                    };\n                                (\n                                    <<\"SIZE=\", Size/binary>>,\n                                    #state{envelope = Envelope} = InnerState\n                                ) ->\n                                    case binary_to_integer(Size) > MaxSize of\n                                        true ->\n                                            {error, [\n                                                \"552 Estimated message length \",\n                                                Size,\n                                                \" exceeds limit of \",\n                                                integer_to_binary(MaxSize),\n                                                \"\\r\\n\"\n                                            ]};\n                                        false ->\n                                            InnerState#state{\n                                                envelope = Envelope#envelope{\n                                                    expectedsize = binary_to_integer(Size)\n                                                }\n                                            }\n                                    end;\n                                (\n                                    <<\"BODY=\", BodyType/binary>>,\n                                    #state{envelope = #envelope{flags = Flags} = Envelope} =\n                                        InnerState\n                                ) ->\n                                    case has_extension(Extensions, \"8BITMIME\") of\n                                        {true, _} ->\n                                            Flag = maps:get(BodyType, #{\n                                                <<\"8BITMIME\">> => '8bitmime',\n                                                <<\"7BIT\">> => '7bit'\n                                            }),\n                                            InnerState#state{\n                                                envelope = Envelope#envelope{flags = [Flag | Flags]}\n                                            };\n                                        false ->\n                                            {error, \"555 Unsupported option BODY\\r\\n\"}\n                                    end;\n                                (\n                                    <<\"SMTPUTF8\">>,\n                                    #state{envelope = #envelope{flags = Flags} = Envelope} =\n                                        InnerState\n                                ) ->\n                                    case has_extension(Extensions, \"SMTPUTF8\") of\n                                        {true, _} ->\n                                            InnerState#state{\n                                                envelope = Envelope#envelope{\n                                                    flags = ['smtputf8' | Flags]\n                                                }\n                                            };\n                                        false ->\n                                            {error, \"555 Unsupported option SMTPUTF8\\r\\n\"}\n                                    end;\n                                (X, InnerState) ->\n                                    case Module:handle_MAIL_extension(X, OldCallbackState) of\n                                        {ok, CallbackState} ->\n                                            InnerState#state{callbackstate = CallbackState};\n                                        error ->\n                                            {error, [\"555 Unsupported option: \", ExtraInfo, \"\\r\\n\"]}\n                                    end\n                            end,\n                            case lists:foldl(F, State, Options) of\n                                {error, Message} ->\n                                    ?LOG_DEBUG(\"error: ~s\", [Message], ?LOGGER_META),\n                                    send(State, Message),\n                                    {ok, State};\n                                #state{envelope = Envelope} = NewState ->\n                                    ?LOG_DEBUG(\"OK\", ?LOGGER_META),\n                                    case Module:handle_MAIL(ParsedAddress, State#state.callbackstate) of\n                                        {ok, CallbackState} ->\n                                            send(State, \"250 sender Ok\\r\\n\"),\n                                            {ok, State#state{\n                                                envelope = Envelope#envelope{from = ParsedAddress},\n                                                callbackstate = CallbackState\n                                            }};\n                                        {error, Message, CallbackState} ->\n                                            send(State, [Message, \"\\r\\n\"]),\n                                            {ok, NewState#state{callbackstate = CallbackState}}\n                                    end\n                            end\n                    end;\n                _Else ->\n                    send(State, \"501 Syntax: MAIL FROM:<address>\\r\\n\"),\n                    {ok, State}\n            end;\n        _Other ->\n            send(State, \"503 Error: Nested MAIL command\\r\\n\"),\n            {ok, State}\n    end;\nhandle_request({<<\"RCPT\">> = C, _Args}, #state{envelope = undefined} = State) ->\n    send(State, \"503 Error: need MAIL command\\r\\n\"),\n    State1 = handle_error(out_of_order, C, State),\n    {ok, State1};\nhandle_request(\n    {<<\"RCPT\">>, Args},\n    #state{\n        envelope = Envelope,\n        module = Module,\n        callbackstate = OldCallbackState,\n        extensions = Extensions\n    } = State\n) ->\n    case binstr:strpos(binstr:to_upper(Args), <<\"TO:\">>) of\n        1 ->\n            Address = binstr:strip(binstr:substr(Args, 4), left, $\\s),\n            case parse_encoded_address(Address, has_extension(Extensions, \"SMTPUTF8\") =/= false) of\n                error ->\n                    send(State, \"501 Bad recipient address syntax\\r\\n\"),\n                    {ok, State};\n                {<<>>, _} ->\n                    % empty rcpt to addresses aren't cool\n                    send(State, \"501 Bad recipient address syntax\\r\\n\"),\n                    {ok, State};\n                {ParsedAddress, <<>>} ->\n                    ?LOG_DEBUG(\"To address ~s (parsed as ~s)\", [Address, ParsedAddress], ?LOGGER_META),\n                    case Module:handle_RCPT(ParsedAddress, OldCallbackState) of\n                        {ok, CallbackState} ->\n                            send(State, \"250 recipient Ok\\r\\n\"),\n                            {ok, State#state{\n                                envelope = Envelope#envelope{\n                                    to = Envelope#envelope.to ++ [ParsedAddress]\n                                },\n                                callbackstate = CallbackState\n                            }};\n                        {error, Message, CallbackState} ->\n                            send(State, [Message, \"\\r\\n\"]),\n                            {ok, State#state{callbackstate = CallbackState}}\n                    end;\n                {ParsedAddress, ExtraInfo} ->\n                    % TODO - are there even any RCPT extensions?\n                    ?LOG_DEBUG(\n                        \"To address ~s (parsed as ~s) with extra info ~s\",\n                        [\n                            Address, ParsedAddress, ExtraInfo\n                        ],\n                        ?LOGGER_META\n                    ),\n                    send(State, [\"555 Unsupported option: \", ExtraInfo, \"\\r\\n\"]),\n                    {ok, State}\n            end;\n        _Else ->\n            send(State, \"501 Syntax: RCPT TO:<address>\\r\\n\"),\n            {ok, State}\n    end;\nhandle_request({<<\"DATA\">> = C, <<>>}, #state{envelope = undefined, protocol = Protocol} = State) ->\n    send(State, [\"503 Error: send \", lhlo_if_lmtp(Protocol, \"HELO/EHLO\"), \" first\\r\\n\"]),\n    State1 = handle_error(out_of_order, C, State),\n    {ok, State1};\nhandle_request({<<\"DATA\">> = C, <<>>}, #state{envelope = Envelope} = State) ->\n    case {Envelope#envelope.from, Envelope#envelope.to} of\n        {undefined, _} ->\n            send(State, \"503 Error: need MAIL command\\r\\n\"),\n            State1 = handle_error(out_of_order, C, State),\n            {ok, State1};\n        {_, []} ->\n            send(State, \"503 Error: need RCPT command\\r\\n\"),\n            State1 = handle_error(out_of_order, C, State),\n            {ok, State1};\n        _Else ->\n            send(State, \"354 enter mail, end with line containing only '.'\\r\\n\"),\n            ?LOG_DEBUG(\"switching to data read mode\", [], ?LOGGER_META),\n\n            {ok, State#state{readmessage = true}}\n    end;\nhandle_request(\n    {<<\"RSET\">>, _Any},\n    #state{envelope = Envelope, module = Module, callbackstate = OldCallbackState} = State\n) ->\n    send(State, \"250 Ok\\r\\n\"),\n    % if the client sends a RSET before a HELO/EHLO don't give them a valid envelope\n    NewEnvelope =\n        case Envelope of\n            undefined -> undefined;\n            _Something -> #envelope{}\n        end,\n    {ok, State#state{envelope = NewEnvelope, callbackstate = Module:handle_RSET(OldCallbackState)}};\nhandle_request({<<\"NOOP\">>, _Any}, State) ->\n    send(State, \"250 Ok\\r\\n\"),\n    {ok, State};\nhandle_request({<<\"QUIT\">>, _Any}, State) ->\n    try_send(State, \"221 Bye\\r\\n\"),\n    {stop, normal, State};\nhandle_request(\n    {<<\"VRFY\">>, Address},\n    #state{module = Module, callbackstate = OldCallbackState, extensions = Extensions} = State\n) ->\n    case parse_encoded_address(Address, has_extension(Extensions, \"SMTPUTF8\") =/= false) of\n        {ParsedAddress, <<>>} ->\n            case Module:handle_VRFY(ParsedAddress, OldCallbackState) of\n                {ok, Reply, CallbackState} ->\n                    send(State, [\"250 \", Reply, \"\\r\\n\"]),\n                    {ok, State#state{callbackstate = CallbackState}};\n                {error, Message, CallbackState} ->\n                    send(State, [Message, \"\\r\\n\"]),\n                    {ok, State#state{callbackstate = CallbackState}}\n            end;\n        _Other ->\n            send(State, \"501 Syntax: VRFY username/address\\r\\n\"),\n            {ok, State}\n    end;\nhandle_request(\n    {<<\"STARTTLS\">>, <<>>},\n    #state{\n        socket = Socket,\n        module = Module,\n        tls = false,\n        extensions = Extensions,\n        callbackstate = OldCallbackState,\n        options = Options\n    } = State\n) ->\n    case has_extension(Extensions, \"STARTTLS\") of\n        {true, _} ->\n            send(State, \"220 OK\\r\\n\"),\n            TlsOpts0 = proplists:get_value(tls_options, Options, []),\n            TlsOpts1 =\n                case proplists:get_value(certfile, Options) of\n                    undefined ->\n                        TlsOpts0;\n                    CertFile ->\n                        [{certfile, CertFile} | TlsOpts0]\n                end,\n            TlsOpts2 =\n                case proplists:get_value(keyfile, Options) of\n                    undefined ->\n                        TlsOpts1;\n                    KeyFile ->\n                        [{keyfile, KeyFile} | TlsOpts1]\n                end,\n            %% Assert that socket is in passive state\n            {ok, [{active, false}]} = inet:getopts(Socket, [active]),\n            %XXX: see smtp_socket:?SSL_LISTEN_OPTIONS\n            case\n                ranch_ssl:handshake(\n                    Socket, [{packet, line}, {mode, list}, {ssl_imp, new} | TlsOpts2], 5000\n                )\n            of\n                {ok, NewSocket} ->\n                    ?LOG_DEBUG(\"SSL negotiation successful\", ?LOGGER_META),\n                    ranch_ssl:setopts(NewSocket, [{packet, line}, binary]),\n                    {ok, State#state{\n                        socket = NewSocket,\n                        transport = ranch_ssl,\n                        envelope = undefined,\n                        authdata = undefined,\n                        waitingauth = false,\n                        readmessage = false,\n                        tls = true,\n                        callbackstate = Module:handle_STARTTLS(OldCallbackState)\n                    }};\n                {error, Reason} ->\n                    ?LOG_INFO(\"SSL handshake failed : ~p\", [Reason], ?LOGGER_META),\n                    send(State, \"454 TLS negotiation failed\\r\\n\"),\n                    State1 = handle_error(ssl_handshake_error, Reason, State),\n                    {ok, State1}\n            end;\n        false ->\n            send(State, \"500 Command unrecognized\\r\\n\"),\n            {ok, State}\n    end;\nhandle_request({<<\"STARTTLS\">> = C, <<>>}, State) ->\n    send(State, \"500 TLS already negotiated\\r\\n\"),\n    State1 = handle_error(out_of_order, C, State),\n    {ok, State1};\nhandle_request({<<\"STARTTLS\">>, _Args}, State) ->\n    send(State, \"501 Syntax error (no parameters allowed)\\r\\n\"),\n    {ok, State};\nhandle_request({Verb, Args}, #state{module = Module, callbackstate = OldCallbackState} = State) ->\n    CallbackState =\n        case Module:handle_other(Verb, Args, OldCallbackState) of\n            {noreply, CState1} ->\n                CState1;\n            {Message, CState1} ->\n                send(State, [Message, \"\\r\\n\"]),\n                CState1\n        end,\n    {ok, State#state{callbackstate = CallbackState}}.\n\n%% @doc handle SASL client response to `334' challenge - RFC-4954\n% the client sends a response to auth-cram-md5\nhandle_sasl(\n    UserDigest,\n    #state{waitingauth = 'cram-md5', envelope = #envelope{auth = {<<>>, <<>>}}, authdata = AuthData} =\n        State\n) ->\n    case binstr:split(UserDigest, <<\" \">>) of\n        [Username, Digest] ->\n            try_auth('cram-md5', Username, {Digest, AuthData}, State#state{authdata = undefined});\n        _ ->\n            % TODO error\n            {ok, State#state{waitingauth = false, authdata = undefined}}\n    end;\n% the client sends a \\0username\\0password response to auth-plain\nhandle_sasl(\n    UserPass, #state{waitingauth = 'plain', envelope = #envelope{auth = {<<>>, <<>>}}} = State\n) ->\n    case binstr:split(UserPass, <<0>>) of\n        [_Identity, Username, Password] ->\n            try_auth('plain', Username, Password, State);\n        [Username, Password] ->\n            try_auth('plain', Username, Password, State);\n        _ ->\n            % TODO error\n            {ok, State#state{waitingauth = false}}\n    end;\n% the client sends a username response to auth-login\nhandle_sasl(\n    Username, #state{waitingauth = 'login', envelope = #envelope{auth = {<<>>, <<>>}}} = State\n) ->\n    Envelope = State#state.envelope,\n    % smtp_socket:send(Socket, \"334 \" ++ base64:encode_to_string(\"Password:\")),\n    send(State, \"334 UGFzc3dvcmQ6\\r\\n\"),\n    % store the provided username in envelope.auth\n    NewState = State#state{envelope = Envelope#envelope{auth = {Username, <<>>}}},\n    {ok, NewState};\n% the client sends a password response to auth-login\nhandle_sasl(\n    Password, #state{waitingauth = 'login', envelope = #envelope{auth = {Username, <<>>}}} = State\n) ->\n    try_auth('login', Username, Password, State).\n\n-spec handle_error(error_class(), any(), #state{}) -> #state{}.\nhandle_error(Kind, Details, #state{module = Module, callbackstate = OldCallbackState} = State) ->\n    case erlang:function_exported(Module, handle_error, 3) of\n        true ->\n            case Module:handle_error(Kind, Details, OldCallbackState) of\n                {ok, CallbackState} ->\n                    State#state{callbackstate = CallbackState};\n                {stop, Reason, CallbackState} ->\n                    throw({stop, Reason, State#state{callbackstate = CallbackState}})\n            end;\n        false ->\n            State\n    end.\n\n%% pa = parse address\n%% ab = angular brackets\n-record(pa, {\n    quotes = false,\n    ab = true,\n    utf8 = false\n}).\n\n%% https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.2\n-spec parse_encoded_address(Address :: binary(), Utf8 :: boolean()) ->\n    {binary(), binary()} | 'error'.\nparse_encoded_address(<<>>, _) ->\n    % empty\n    error;\nparse_encoded_address(<<\"<@\", Address/binary>>, Utf8) ->\n    %% A-d-l (source route) - should be ignored\n    case binstr:strchr(Address, $:) of\n        0 ->\n            % invalid address\n            error;\n        Index ->\n            parse_encoded_address(binstr:substr(Address, Index + 1), [], #pa{\n                quotes = false, ab = true, utf8 = Utf8\n            })\n    end;\nparse_encoded_address(<<\"<\", Address/binary>>, Utf8) ->\n    parse_encoded_address(Address, [], #pa{quotes = false, ab = true, utf8 = Utf8});\nparse_encoded_address(<<\" \", Address/binary>>, Utf8) ->\n    parse_encoded_address(Address, Utf8);\nparse_encoded_address(Address, Utf8) ->\n    parse_encoded_address(Address, [], #pa{quotes = false, ab = false, utf8 = Utf8}).\n\n-spec parse_encoded_address(Address :: binary(), Acc :: list(), Flags :: #pa{}) ->\n    {binary(), binary()} | 'error'.\nparse_encoded_address(<<>>, Acc, #pa{ab = false}) ->\n    {unicode:characters_to_binary(lists:reverse(Acc)), <<>>};\nparse_encoded_address(<<>>, _Acc, #pa{ab = true}) ->\n    % began with angle brackets but didn't end with them\n    error;\nparse_encoded_address(_, Acc, _) when length(Acc) > 320 ->\n    % too long\n    error;\nparse_encoded_address(<<\"\\\\\", H, Tail/binary>>, Acc, Flags) ->\n    parse_encoded_address(Tail, [H | Acc], Flags);\nparse_encoded_address(<<\"\\\"\", Tail/binary>>, Acc, #pa{quotes = false} = F) ->\n    parse_encoded_address(Tail, Acc, F#pa{quotes = true});\nparse_encoded_address(<<\"\\\"\", Tail/binary>>, Acc, #pa{quotes = true} = F) ->\n    parse_encoded_address(Tail, Acc, F#pa{quotes = false});\nparse_encoded_address(<<\">\", Tail/binary>>, Acc, #pa{quotes = false, ab = true}) ->\n    {unicode:characters_to_binary(lists:reverse(Acc)), binstr:strip(Tail, left, $\\s)};\nparse_encoded_address(<<\">\", _Tail/binary>>, _Acc, #pa{quotes = false, ab = false}) ->\n    % ended with angle brackets but didn't begin with them\n    error;\nparse_encoded_address(<<\" \", Tail/binary>>, Acc, #pa{quotes = false, ab = false}) ->\n    {unicode:characters_to_binary(lists:reverse(Acc)), binstr:strip(Tail, left, $\\s)};\nparse_encoded_address(<<\" \", _Tail/binary>>, _Acc, #pa{quotes = false, ab = true}) ->\n    % began with angle brackets but didn't end with them\n    error;\nparse_encoded_address(<<H/utf8, Tail/binary>>, Acc, #pa{utf8 = true} = F) when H > 127 ->\n    %% https://datatracker.ietf.org/doc/html/rfc6531#section-3.3\n\n    % UTF-8 above 7bit (when allowed)\n    parse_encoded_address(Tail, [H | Acc], F);\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = false} = F) when H >= $0, H =< $9 ->\n    % digits\n    parse_encoded_address(Tail, [H | Acc], F);\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = false} = F) when H >= $@, H =< $Z ->\n    % @ symbol and uppercase letters\n    parse_encoded_address(Tail, [H | Acc], F);\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = false} = F) when H >= $a, H =< $z ->\n    % lowercase letters\n    parse_encoded_address(Tail, [H | Acc], F);\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = false} = F) when\n    H =:= $-; H =:= $.; H =:= $_\n->\n    % dash, dot, underscore\n    parse_encoded_address(Tail, [H | Acc], F);\n% Allowed characters in the local name: ! # $ % & ' * + - / = ?  ^ _ ` . { | } ~\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = false} = F) when\n    H =:= $+;\n    H =:= $!;\n    H =:= $#;\n    H =:= $$;\n    H =:= $%;\n    H =:= $&;\n    H =:= $';\n    H =:= $*;\n    H =:= $=;\n    H =:= $/;\n    H =:= $?;\n    H =:= $^;\n    H =:= $`;\n    H =:= ${;\n    H =:= $|;\n    H =:= $};\n    H =:= $~\n->\n    % other characters\n    parse_encoded_address(Tail, [H | Acc], F);\nparse_encoded_address(_, _Acc, #pa{quotes = false}) ->\n    error;\nparse_encoded_address(<<H, Tail/binary>>, Acc, #pa{quotes = true} = F) ->\n    parse_encoded_address(Tail, [H | Acc], F).\n\n-spec has_extension(Extensions :: [{string(), string()}], Extension :: string()) ->\n    {'true', string()} | 'false'.\nhas_extension(Extensions, Ext) ->\n    ?LOG_DEBUG(\"extensions ~p\", [Extensions], ?LOGGER_META),\n    case proplists:get_value(Ext, Extensions) of\n        undefined ->\n            false;\n        Value ->\n            {true, Value}\n    end.\n\n-spec try_auth(\n    AuthType :: 'login' | 'plain' | 'cram-md5',\n    Username :: binary(),\n    Credential :: binary() | {binary(), binary()},\n    State :: #state{}\n) -> {'ok', #state{}}.\ntry_auth(\n    AuthType,\n    Username,\n    Credential,\n    #state{module = Module, envelope = Envelope, callbackstate = OldCallbackState} = State\n) ->\n    % clear out waiting auth\n    NewState = State#state{waitingauth = false, envelope = Envelope#envelope{auth = {<<>>, <<>>}}},\n    case erlang:function_exported(Module, handle_AUTH, 4) of\n        true ->\n            case Module:handle_AUTH(AuthType, Username, Credential, OldCallbackState) of\n                {ok, CallbackState} ->\n                    send(State, \"235 Authentication successful.\\r\\n\"),\n                    {ok, NewState#state{\n                        callbackstate = CallbackState,\n                        envelope = Envelope#envelope{auth = {Username, Credential}}\n                    }};\n                _Other ->\n                    send(State, \"535 Authentication failed.\\r\\n\"),\n                    {ok, NewState}\n            end;\n        false ->\n            ?LOG_WARNING(\n                \"Please define handle_AUTH/4 in your server module or remove AUTH from your module extensions\",\n                ?LOGGER_META\n            ),\n            send(State, \"535 authentication failed (#5.7.1)\\r\\n\"),\n            {ok, NewState}\n    end.\n\n%get_digest_nonce() ->\n%A = [io_lib:format(\"~2.16.0b\", [X]) || <<X>> <= erlang:md5(integer_to_list(rand:uniform(4294967295)))],\n%B = [io_lib:format(\"~2.16.0b\", [X]) || <<X>> <= erlang:md5(integer_to_list(rand:uniform(4294967295)))],\n%binary_to_list(base64:encode(lists:flatten(A ++ B))).\n\n%% @doc a tight loop to receive the message body\nreceive_data(_Acc, _Transport, _Socket, _, Size, MaxSize, Session, _Options) when\n    MaxSize =/= 'infinity', Size > MaxSize\n->\n    ?LOG_INFO(\"SMTP message body size ~B exceeded maximum allowed ~B\", [Size, MaxSize], ?LOGGER_META),\n    Session ! {receive_data, {error, size_exceeded}};\nreceive_data(Acc, Transport, Socket, RecvSize, Size, MaxSize, Session, Options) ->\n    case Transport:recv(Socket, RecvSize, 1000) of\n        {ok, Packet} when Acc =:= [] ->\n            case\n                check_bare_crlf(\n                    Packet, <<>>, proplists:get_value(allow_bare_newlines, Options, false), 0\n                )\n            of\n                error ->\n                    Session ! {receive_data, {error, bare_newline}};\n                FixedPacket ->\n                    case binstr:strpos(FixedPacket, <<\"\\r\\n.\\r\\n\">>) of\n                        0 ->\n                            ?LOG_DEBUG(\n                                \"received ~B bytes; size is now ~p\",\n                                [\n                                    RecvSize, Size + size(Packet)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            ?LOG_DEBUG(\"memory usage: ~p\", [erlang:process_info(self(), memory)], ?LOGGER_META),\n                            receive_data(\n                                [FixedPacket | Acc],\n                                Transport,\n                                Socket,\n                                RecvSize,\n                                Size + byte_size(FixedPacket),\n                                MaxSize,\n                                Session,\n                                Options\n                            );\n                        Index ->\n                            String = binstr:substr(FixedPacket, 1, Index - 1),\n                            Rest = binstr:substr(FixedPacket, Index + 5),\n                            ?LOG_DEBUG(\n                                \"memory usage before flattening: ~p\",\n                                [\n                                    erlang:process_info(self(), memory)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            Result = list_to_binary(lists:reverse([String | Acc])),\n                            ?LOG_DEBUG(\n                                \"memory usage after flattening: ~p\",\n                                [\n                                    erlang:process_info(self(), memory)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            Session ! {receive_data, Result, Rest}\n                    end\n            end;\n        {ok, Packet} ->\n            [Last | _] = Acc,\n            case\n                check_bare_crlf(\n                    Packet, Last, proplists:get_value(allow_bare_newlines, Options, false), 0\n                )\n            of\n                error ->\n                    Session ! {receive_data, {error, bare_newline}};\n                FixedPacket ->\n                    case binstr:strpos(FixedPacket, <<\"\\r\\n.\\r\\n\">>) of\n                        0 ->\n                            ?LOG_DEBUG(\n                                \"received ~B bytes; size is now ~p\",\n                                [\n                                    RecvSize, Size + size(Packet)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            ?LOG_DEBUG(\"memory usage: ~p\", [erlang:process_info(self(), memory)], ?LOGGER_META),\n                            receive_data(\n                                [FixedPacket | Acc],\n                                Transport,\n                                Socket,\n                                RecvSize,\n                                Size + byte_size(FixedPacket),\n                                MaxSize,\n                                Session,\n                                Options\n                            );\n                        Index ->\n                            String = binstr:substr(FixedPacket, 1, Index - 1),\n                            Rest = binstr:substr(FixedPacket, Index + 5),\n                            ?LOG_DEBUG(\n                                \"memory usage before flattening: ~p\",\n                                [\n                                    erlang:process_info(self(), memory)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            Result = list_to_binary(lists:reverse([String | Acc])),\n                            ?LOG_DEBUG(\n                                \"memory usage after flattening: ~p\",\n                                [\n                                    erlang:process_info(self(), memory)\n                                ],\n                                ?LOGGER_META\n                            ),\n                            Session ! {receive_data, Result, Rest}\n                    end\n            end;\n        {error, timeout} when RecvSize =:= 0, length(Acc) > 1 ->\n            % check that we didn't accidentally receive a \\r\\n.\\r\\n split across 2 receives\n            [A, B | Acc2] = Acc,\n            Packet = list_to_binary([B, A]),\n            case binstr:strpos(Packet, <<\"\\r\\n.\\r\\n\">>) of\n                0 ->\n                    % uh-oh\n                    ?LOG_DEBUG(\n                        \"no data on socket, and no DATA terminator, retrying ~p\",\n                        [\n                            Session\n                        ],\n                        ?LOGGER_META\n                    ),\n                    % eventually we'll either get data or a different error, just keep retrying\n                    receive_data(Acc, Transport, Socket, 0, Size, MaxSize, Session, Options);\n                Index ->\n                    String = binstr:substr(Packet, 1, Index - 1),\n                    Rest = binstr:substr(Packet, Index + 5),\n                    ?LOG_DEBUG(\n                        \"memory usage before flattening: ~p\",\n                        [\n                            erlang:process_info(self(), memory)\n                        ],\n                        ?LOGGER_META\n                    ),\n                    Result = list_to_binary(lists:reverse([String | Acc2])),\n                    ?LOG_DEBUG(\n                        \"memory usage after flattening: ~p\",\n                        [\n                            erlang:process_info(self(), memory)\n                        ],\n                        ?LOGGER_META\n                    ),\n                    Session ! {receive_data, Result, Rest}\n            end;\n        {error, timeout} ->\n            receive_data(Acc, Transport, Socket, 0, Size, MaxSize, Session, Options);\n        {error, Reason} ->\n            ?LOG_WARNING(\"SMTP receive error: ~p\", [Reason], ?LOGGER_META),\n            Session ! {receive_data, {error, Reason}}\n    end.\n\ncheck_for_bare_crlf(Bin, Offset) ->\n    case\n        {\n            re:run(Bin, \"(?<!\\r)\\n\", [{capture, none}, {offset, Offset}]),\n            re:run(Bin, \"\\r(?!\\n)\", [{capture, none}, {offset, Offset}])\n        }\n    of\n        {match, _} -> true;\n        {_, match} -> true;\n        _ -> false\n    end.\n\nfix_bare_crlf(Bin, Offset) ->\n    Options = [{offset, Offset}, {return, binary}, global],\n    re:replace(re:replace(Bin, \"(?<!\\r)\\n\", \"\\r\\n\", Options), \"\\r(?!\\n)\", \"\\r\\n\", Options).\n\nstrip_bare_crlf(Bin, Offset) ->\n    Options = [{offset, Offset}, {return, binary}, global],\n    re:replace(re:replace(Bin, \"(?<!\\r)\\n\", \"\", Options), \"\\r(?!\\n)\", \"\", Options).\n\ncheck_bare_crlf(Binary, _, ignore, _) ->\n    Binary;\ncheck_bare_crlf(<<$\\n, _Rest/binary>> = Bin, Prev, Op, 0 = _Offset) when byte_size(Prev) > 0 ->\n    % check if last character of previous was a CR\n    Lastchar = binstr:substr(Prev, -1),\n    case Lastchar of\n        <<\"\\r\">> ->\n            % okay, check again for the rest\n            check_bare_crlf(Bin, <<>>, Op, 1);\n        % not fixing or ignoring them\n        _ when Op == false ->\n            error;\n        _ ->\n            % no dice\n            check_bare_crlf(Bin, <<>>, Op, 0)\n    end;\ncheck_bare_crlf(Binary, _Prev, Op, Offset) ->\n    Last = binstr:substr(Binary, -1),\n    % is the last character a CR?\n    case Last of\n        <<\"\\r\">> ->\n            % okay, the last character is a CR, we have to assume the next packet contains the corresponding LF\n            NewBin = binstr:substr(Binary, 1, byte_size(Binary) - 1),\n            case check_for_bare_crlf(NewBin, Offset) of\n                true when Op == fix ->\n                    list_to_binary([fix_bare_crlf(NewBin, Offset), \"\\r\"]);\n                true when Op == strip ->\n                    list_to_binary([strip_bare_crlf(NewBin, Offset), \"\\r\"]);\n                true ->\n                    error;\n                false ->\n                    Binary\n            end;\n        _ ->\n            case check_for_bare_crlf(Binary, Offset) of\n                true when Op == fix ->\n                    fix_bare_crlf(Binary, Offset);\n                true when Op == strip ->\n                    strip_bare_crlf(Binary, Offset);\n                true ->\n                    error;\n                false ->\n                    Binary\n            end\n    end.\n\ntry_send(#state{transport = Transport, socket = Sock}, Data) ->\n    Transport:send(Sock, Data),\n    ok.\n\nsend(#state{transport = Transport, socket = Sock} = St, Data) ->\n    case Transport:send(Sock, Data) of\n        ok ->\n            ok;\n        {error, Err} ->\n            St1 = handle_error(send_error, Err, St),\n            throw({stop, {send_error, Err}, St1})\n    end.\n\nsetopts(#state{transport = Transport, socket = Sock} = St, Opts) ->\n    case Transport:setopts(Sock, Opts) of\n        ok ->\n            ok;\n        {error, Err} ->\n            St1 = handle_error(setopts_error, Err, St),\n            throw({stop, {setopts_error, Err}, St1})\n    end.\n\nhostname(Opts) ->\n    proplists:get_value(hostname, Opts, smtp_util:guess_FQDN()).\n\n%% @hidden\nlhlo_if_lmtp(Protocol, Fallback) ->\n    case Protocol == lmtp of\n        true -> \"LHLO\";\n        false -> Fallback\n    end.\n\n%% @hidden\n-spec report_recipient(\n    ResponseType :: 'ok' | 'error' | 'multiple',\n    Value :: string() | [{'ok' | 'error', string()}],\n    State :: #state{}\n) -> any().\nreport_recipient(ok, Reference, State) ->\n    send(State, [\"250 \", Reference, \"\\r\\n\"]);\nreport_recipient(error, Message, State) ->\n    send(State, [Message, \"\\r\\n\"]);\nreport_recipient(multiple, _Any, #state{protocol = smtp} = State) ->\n    Msg = \"SMTP should report a single delivery status for all the recipients\",\n    throw({stop, {handle_DATA_error, Msg}, State});\nreport_recipient(multiple, [], _State) ->\n    ok;\nreport_recipient(multiple, [{ResponseType, Value} | Rest], State) ->\n    report_recipient(ResponseType, Value, State),\n    report_recipient(multiple, Rest, State).\n\n-ifdef(TEST).\nparse_encoded_address_test_() ->\n    [\n        {\"Valid addresses should parse\", fun() ->\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<God@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<\\\\God@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<\\\"God\\\"@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(\n                    <<\"<@gateway.af.mil,@uucp.local:\\\"\\\\G\\\\o\\\\d\\\"@heaven.af.mil>\">>, false\n                )\n            ),\n            ?assertEqual(\n                {<<\"God2@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<God2@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God+extension@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<God+extension@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God~*$@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<God~*$@heaven.af.mil>\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God~!#$%^&*()_+123@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"<\\\"God~!#$%^&*()_+123\\\"@heaven.af.mil>\">>, false)\n            )\n        end},\n        {\"Addresses that are sorta valid should parse\", fun() ->\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"God@heaven.af.mil\">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\"God@heaven.af.mil \">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\" God@heaven.af.mil \">>, false)\n            ),\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<>>},\n                parse_encoded_address(<<\" <God@heaven.af.mil> \">>, false)\n            )\n        end},\n        {\"Addresses with UTF8 characters should parse only when allowed\", fun() ->\n            %% https://www.iana.org/domains/reserved\n            ?assertEqual(\n                {<<\"испытание@пример.испытание\"/utf8>>, <<>>},\n                parse_encoded_address(<<\"<испытание@пример.испытание>\"/utf8>>, true)\n            ),\n            ?assertEqual(\n                {<<\"測試@例子.測試\"/utf8>>, <<>>},\n                parse_encoded_address(<<\"<測試@例子.測試>\"/utf8>>, true)\n            ),\n            ?assertEqual(\n                {<<\"испытание@пример.испытание\"/utf8>>, <<\"SIZE=100\">>},\n                parse_encoded_address(<<\"<испытание@пример.испытание> SIZE=100\"/utf8>>, true)\n            ),\n            ?assertEqual(\n                {<<\"test@пример.испытание\"/utf8>>, <<>>},\n                parse_encoded_address(<<\"<test@пример.испытание>\"/utf8>>, true)\n            ),\n            ?assertEqual(\n                {<<\"испытание!#¤½§´`<>@пример.испытание\"/utf8>>, <<>>},\n                parse_encoded_address(<<\"<\\\"испытание!#¤½§´`<>\\\"@пример.испытание>\"/utf8>>, true)\n            ),\n            ?assertEqual(\n                error, parse_encoded_address(<<\"<испытание@пример.испытание>\"/utf8>>, false)\n            )\n        end},\n        {\"Addresses containing unescaped <> that aren't at start/end should fail\", fun() ->\n            ?assertEqual(error, parse_encoded_address(<<\"<<\">>, false)),\n            ?assertEqual(error, parse_encoded_address(<<\"<God<@heaven.af.mil>\">>, false))\n        end},\n        {\"Address that begins with < but doesn't end with a > should fail\", fun() ->\n            ?assertEqual(error, parse_encoded_address(<<\"<God@heaven.af.mil\">>, false)),\n            ?assertEqual(error, parse_encoded_address(<<\"<God@heaven.af.mil \">>, false))\n        end},\n        {\"Address that begins without < but ends with a > should fail\", fun() ->\n            ?assertEqual(error, parse_encoded_address(<<\"God@heaven.af.mil>\">>, false))\n        end},\n        {\"Address longer than 320 characters should fail\", fun() ->\n            MegaAddress = list_to_binary(\n                lists:seq(97, 122) ++ lists:seq(97, 122) ++ lists:seq(97, 122) ++ lists:seq(97, 122) ++\n                    lists:seq(97, 122) ++ lists:seq(97, 122) ++ \"@\" ++ lists:seq(97, 122) ++\n                    lists:seq(97, 122) ++ lists:seq(97, 122) ++ lists:seq(97, 122) ++\n                    lists:seq(97, 122) ++ lists:seq(97, 122) ++ lists:seq(97, 122)\n            ),\n            ?assertEqual(error, parse_encoded_address(MegaAddress, false))\n        end},\n        {\"Address with an invalid route should fail\", fun() ->\n            ?assertEqual(\n                error, parse_encoded_address(<<\"<@gateway.af.mil God@heaven.af.mil>\">>, false)\n            )\n        end},\n        {\"Empty addresses should parse OK\", fun() ->\n            ?assertEqual({<<>>, <<>>}, parse_encoded_address(<<\"<>\">>, false)),\n            ?assertEqual({<<>>, <<>>}, parse_encoded_address(<<\" <> \">>, false))\n        end},\n        {\"Completely empty addresses are an error\", fun() ->\n            ?assertEqual(error, parse_encoded_address(<<\"\">>, false)),\n            ?assertEqual(error, parse_encoded_address(<<\" \">>, false))\n        end},\n        {\"addresses with trailing parameters should return the trailing parameters\", fun() ->\n            ?assertEqual(\n                {<<\"God@heaven.af.mil\">>, <<\"SIZE=100 BODY=8BITMIME\">>},\n                parse_encoded_address(<<\"<God@heaven.af.mil> SIZE=100 BODY=8BITMIME\">>, false)\n            )\n        end}\n    ].\n\nparse_request_test_() ->\n    [\n        {\"Parsing normal SMTP requests\", fun() ->\n            ?assertEqual({<<\"HELO\">>, <<>>}, parse_request(<<\"HELO\\r\\n\">>)),\n            ?assertEqual(\n                {<<\"EHLO\">>, <<\"hell.af.mil\">>}, parse_request(<<\"EHLO hell.af.mil\\r\\n\">>)\n            ),\n            ?assertEqual(\n                {<<\"LHLO\">>, <<\"hell.af.mil\">>}, parse_request(<<\"LHLO hell.af.mil\\r\\n\">>)\n            ),\n            ?assertEqual(\n                {<<\"MAIL\">>, <<\"FROM:God@heaven.af.mil\">>},\n                parse_request(<<\"MAIL FROM:God@heaven.af.mil\">>)\n            )\n        end},\n        {\"Verbs should be uppercased\", fun() ->\n            ?assertEqual({<<\"HELO\">>, <<\"hell.af.mil\">>}, parse_request(<<\"helo hell.af.mil\">>)),\n            ?assertEqual({<<\"RSET\">>, <<>>}, parse_request(<<\"rset\\r\\n\">>))\n        end},\n        {\"Leading and trailing spaces are removed\", fun() ->\n            ?assertEqual(\n                {<<\"HELO\">>, <<\"hell.af.mil\">>}, parse_request(<<\" helo   hell.af.mil           \">>)\n            )\n        end},\n        {\"Blank lines are blank\", fun() ->\n            ?assertEqual({<<>>, <<>>}, parse_request(<<\"\">>))\n        end}\n    ].\n\nsmtp_session_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"A new connection should get a banner\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> ok\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A correct response to HELO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 localhost\\r\\n\", Packet2)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An error in response to an invalid HELO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"501 Syntax: HELO hostname\\r\\n\", Packet2)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An error in response to an LHLO sent by SMTP\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"LHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\n                        \"500 Error: SMTP should send HELO or EHLO instead of LHLO\\r\\n\", Packet2\n                    )\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A rejected HELO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO invalid\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"554 invalid hostname\\r\\n\", Packet2)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A rejected EHLO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO invalid\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"554 invalid hostname\\r\\n\", Packet2)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"EHLO response\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F) ->\n                        receive\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F);\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                ok;\n                            {tcp, CSock, _R} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(ok, Foo(Foo))\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Unsupported AUTH PLAIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F) ->\n                        receive\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F);\n                            {tcp, CSock, \"250\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                ok;\n                            {tcp, CSock, _R} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(ok, Foo(Foo)),\n                    smtp_socket:send(CSock, \"AUTH PLAIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"502 Error: AUTH not implemented\\r\\n\", Packet4)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Sending DATA\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 localhost\\r\\n\", Packet2),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<user@otherhost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"message body\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 queued as\" ++ _, Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Sending with spaced MAIL FROM / RCPT TO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 localhost\\r\\n\", Packet2),\n                    smtp_socket:send(CSock, \"MAIL FROM: <user@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO: <user@otherhost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"message body\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 queued as\" ++ _, Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Sending with UTF8 addresses and body\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    receive\n                        {tcp, CSock, Packet31} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-SIZE\" ++ _, Packet31),\n                    receive\n                        {tcp, CSock, Packet32} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-8BITMIME\" ++ _, Packet32),\n                    receive\n                        {tcp, CSock, Packet33} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-PIPELINING\" ++ _, Packet33),\n                    receive\n                        {tcp, CSock, Packet34} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 SMTPUTF8\" ++ _, Packet34),\n                    smtp_socket:send(\n                        CSock, <<\"MAIL FROM: <испытание@пример.испытание> SMTPUTF8\\r\\n\"/utf8>>\n                    ),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 sender Ok\" ++ _, Packet4),\n                    smtp_socket:send(CSock, <<\"RCPT TO: <測試@例子.測試>\\r\\n\"/utf8>>),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 recipient Ok\" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet6),\n                    smtp_socket:send(CSock, <<\"Subject: Я помню чудное мгновенье\\r\\n\"/utf8>>),\n                    smtp_socket:send(CSock, <<\"To: <測試@例子.測試>\\r\\n\"/utf8>>),\n                    smtp_socket:send(CSock, <<\"From: <испытание@пример.испытание>\\r\\n\"/utf8>>),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, <<\"Передо мной явилась ты\"/utf8>>),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet7} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 queued as\" ++ _, Packet7)\n                end}\n            end,\n            %\t\t\tfun({CSock, _Pid}) ->\n            %\t\t\t\t\t{\"Sending DATA with a bare newline\",\n            %\t\t\t\t\t\tfun() ->\n            %\t\t\t\t\t\t\t\tsmtp_socket:active_once(CSock),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"220 localhost\"++_Stuff,  Packet),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 localhost\\r\\n\",  Packet2),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet3),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"RCPT TO: <user@otherhost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet4),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"DATA\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"354 \"++_, Packet5),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"this\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"body\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"has\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"a\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"bare\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"newline\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"451 \"++_, Packet6),\n            %\t\t\t\t\t\tend\n            %\t\t\t\t\t}\n            %\t\t\tend,\n            %fun({CSock, _Pid}) ->\n            %\t\t\t\t\t{\"Sending DATA with a bare CR\",\n            %\t\t\t\t\t\tfun() ->\n            %\t\t\t\t\t\t\t\tsmtp_socket:active_once(CSock),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"220 localhost\"++_Stuff,  Packet),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 localhost\\r\\n\",  Packet2),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet3),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"RCPT TO: <user@otherhost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet4),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"DATA\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"354 \"++_, Packet5),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"this\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\rbody\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"has\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"a\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"bare\\r\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"CR\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"451 \"++_, Packet6),\n            %\t\t\t\t\t\tend\n            %\t\t\t\t\t}\n            %\t\t\tend,\n\n            %\t\t\tfun({CSock, _Pid}) ->\n            %\t\t\t\t\t{\"Sending DATA with a bare newline in the headers\",\n            %\t\t\t\t\t\tfun() ->\n            %\t\t\t\t\t\t\t\tsmtp_socket:active_once(CSock),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"220 localhost\"++_Stuff,  Packet),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 localhost\\r\\n\",  Packet2),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet3),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"RCPT TO: <user@otherhost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"250 \"++_, Packet4),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"DATA\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"354 \"++_, Packet5),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"To: <user@otherhost>\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"this\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"body\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"has\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"no\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"bare\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"newlines\\r\\n\"),\n            %\t\t\t\t\t\t\t\tsmtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n            %\t\t\t\t\t\t\t\treceive {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock) end,\n            %\t\t\t\t\t\t\t\t?assertMatch(\"451 \"++_, Packet6),\n            %\t\t\t\t\t\tend\n            %\t\t\t\t\t}\n            %\t\t\tend,\n            fun({CSock, _Pid}) ->\n                {\"Sending DATA with bare newline on first line of body\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 localhost\\r\\n\", Packet2),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<user@otherhost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"this\\n\"),\n                    smtp_socket:send(CSock, \"body\\r\\n\"),\n                    smtp_socket:send(CSock, \"has\\r\\n\"),\n                    smtp_socket:send(CSock, \"no\\r\\n\"),\n                    smtp_socket:send(CSock, \"bare\\r\\n\"),\n                    smtp_socket:send(CSock, \"newlines\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"451 \" ++ _, Packet6)\n                end}\n            end\n        ]}.\n\nlmtp_session_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [\n                        {protocol, lmtp},\n                        {callbackoptions, [\n                            {protocol, lmtp},\n                            {size, infinity}\n                        ]}\n                    ]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"An error in response to a HELO/EHLO sent by LMTP\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"HELO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\n                        \"500 Error: LMTP should replace HELO and EHLO with LHLO\\r\\n\", Packet2\n                    ),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\n                        \"500 Error: LMTP should replace HELO and EHLO with LHLO\\r\\n\", Packet3\n                    )\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"LHLO response\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"LHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F) ->\n                        receive\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F);\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                ok;\n                            {tcp, CSock, _R} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(ok, Foo(Foo))\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"DATA with multiple RCPT TO\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"LHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE\" ++ _ = Data} ->\n                                {error, [\"received: \", Data]};\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, Data} ->\n                                smtp_socket:active_once(CSock),\n                                {error, [\"received: \", Data]}\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<test1@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"RCPT TO:<test2@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"RCPT TO:<test3@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet6),\n\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet7} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet7),\n\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"message body\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    % We sent 3 RCPT TO, so we should have 3 delivery reports\n                    AssertDelivery = fun(_) ->\n                        receive\n                            {tcp, CSock, Packet8} -> smtp_socket:active_once(CSock)\n                        end,\n                        ?assertMatch(\"250 \" ++ _, Packet8)\n                    end,\n                    lists:foreach(AssertDelivery, [1, 2, 3]),\n                    smtp_socket:send(CSock, \"QUIT\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet9} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"221 \" ++ _, Packet9)\n                end}\n            end\n        ]}.\n\nsmtp_session_auth_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [{callbackoptions, [{auth, true}]}]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"EHLO response includes AUTH\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false))\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"AUTH before EHLO is error\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"AUTH CRAZY\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"503 \" ++ _, Packet4)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Unknown authentication type\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH CRAZY\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"504 Unrecognized authentication type\\r\\n\", Packet4)\n                end}\n            end,\n\n            fun({CSock, _Pid}) ->\n                {\"A successful AUTH PLAIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH PLAIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334\\r\\n\", Packet4),\n                    String = binary_to_list(base64:encode(\"\\0username\\0PaSSw0rd\")),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A successful AUTH PLAIN with an identity\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH PLAIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334\\r\\n\", Packet4),\n                    String = binary_to_list(base64:encode(\"username\\0username\\0PaSSw0rd\")),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A successful immediate AUTH PLAIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    String = binary_to_list(base64:encode(\"\\0username\\0PaSSw0rd\")),\n                    smtp_socket:send(CSock, \"AUTH PLAIN \" ++ String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A successful immediate AUTH PLAIN with an identity\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _R} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    String = binary_to_list(base64:encode(\"username\\0username\\0PaSSw0rd\")),\n                    smtp_socket:send(CSock, \"AUTH PLAIN \" ++ String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An unsuccessful immediate AUTH PLAIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    String = binary_to_list(base64:encode(\"username\\0username\\0PaSSw0rd2\")),\n                    smtp_socket:send(CSock, \"AUTH PLAIN \" ++ String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"535 Authentication failed.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An unsuccessful AUTH PLAIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH PLAIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334\\r\\n\", Packet4),\n                    String = binary_to_list(base64:encode(\"\\0username\\0NotThePassword\")),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"535 Authentication failed.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A successful AUTH LOGIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH LOGIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 VXNlcm5hbWU6\\r\\n\", Packet4),\n                    String = binary_to_list(base64:encode(\"username\")),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 UGFzc3dvcmQ6\\r\\n\", Packet5),\n                    PString = binary_to_list(base64:encode(\"PaSSw0rd\")),\n                    smtp_socket:send(CSock, PString ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An unsuccessful AUTH LOGIN\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH LOGIN\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 VXNlcm5hbWU6\\r\\n\", Packet4),\n                    String = binary_to_list(base64:encode(\"username2\")),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 UGFzc3dvcmQ6\\r\\n\", Packet5),\n                    PString = binary_to_list(base64:encode(\"PaSSw0rd\")),\n                    smtp_socket:send(CSock, PString ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet6} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"535 Authentication failed.\\r\\n\", Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"A successful AUTH CRAM-MD5\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH CRAM-MD5\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 \" ++ _, Packet4),\n\n                    [\"334\", Seed64] = string:tokens(smtp_util:trim_crlf(Packet4), \" \"),\n                    Seed = base64:decode_to_string(Seed64),\n                    Digest = smtp_util:compute_cram_digest(\"PaSSw0rd\", Seed),\n                    String = binary_to_list(base64:encode(list_to_binary([\"username \", Digest]))),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"235 Authentication successful.\\r\\n\", Packet5)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"An unsuccessful AUTH CRAM-MD5\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 AUTH\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"AUTH CRAM-MD5\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"334 \" ++ _, Packet4),\n\n                    [\"334\", Seed64] = string:tokens(smtp_util:trim_crlf(Packet4), \" \"),\n                    Seed = base64:decode_to_string(Seed64),\n                    Digest = smtp_util:compute_cram_digest(\"Passw0rd\", Seed),\n                    String = binary_to_list(base64:encode(list_to_binary([\"username \", Digest]))),\n                    smtp_socket:send(CSock, String ++ \"\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"535 Authentication failed.\\r\\n\", Packet5)\n                end}\n            end\n        ]}.\n\nsmtp_session_tls_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [\n                        {tls_options, [\n                            {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                            {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                        ]},\n                        {callbackoptions, [{auth, true}]}\n                    ]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"EHLO response includes STARTTLS\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false))\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"STARTTLS does a SSL handshake\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> ok\n                    end,\n                    ?assertMatch(\"220 \" ++ _, Packet4),\n                    Result = smtp_socket:to_ssl_client(CSock),\n                    ?assertMatch({ok, _Socket}, Result),\n                    {ok, _Socket} = Result\n                %smtp_socket:active_once(Socket),\n                %ssl:send(Socket, \"EHLO somehost.com\\r\\n\"),\n                %receive {ssl, Socket, Packet5} -> smtp_socket:active_once(Socket) end,\n                %?assertEqual(\"Foo\", Packet5),\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"After STARTTLS, EHLO doesn't report STARTTLS\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> ok\n                    end,\n                    ?assertMatch(\"220 \" ++ _, Packet4),\n                    Result = smtp_socket:to_ssl_client(CSock),\n                    ?assertMatch({ok, _Socket}, Result),\n                    {ok, Socket} = Result,\n                    smtp_socket:active_once(Socket),\n                    smtp_socket:send(Socket, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet5} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet5),\n                    Bar = fun(F, Acc) ->\n                        receive\n                            {ssl, Socket, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, true);\n                            {ssl, Socket, \"250-\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, Acc);\n                            {ssl, Socket, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                true;\n                            {ssl, Socket, \"250 \" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                Acc;\n                            {ssl, Socket, _} ->\n                                smtp_socket:active_once(Socket),\n                                error\n                        end\n                    end,\n                    ?assertEqual(false, Bar(Bar, false))\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"After STARTTLS, re-negotiating STARTTLS is an error\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> ok\n                    end,\n                    ?assertMatch(\"220 \" ++ _, Packet4),\n                    Result = smtp_socket:to_ssl_client(CSock),\n                    ?assertMatch({ok, _Socket}, Result),\n                    {ok, Socket} = Result,\n                    smtp_socket:active_once(Socket),\n                    smtp_socket:send(Socket, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet5} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet5),\n                    Bar = fun(F, Acc) ->\n                        receive\n                            {ssl, Socket, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, true);\n                            {ssl, Socket, \"250-\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, Acc);\n                            {ssl, Socket, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                true;\n                            {ssl, Socket, \"250 \" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                Acc;\n                            {ssl, Socket, _} ->\n                                smtp_socket:active_once(Socket),\n                                error\n                        end\n                    end,\n                    ?assertEqual(false, Bar(Bar, false)),\n                    smtp_socket:send(Socket, \"STARTTLS\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet6} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"500 \" ++ _, Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"STARTTLS can't take any parameters\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"STARTTLS foo\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> ok\n                    end,\n                    ?assertMatch(\"501 \" ++ _, Packet4)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Negotiating STARTTLS twice is an error\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, _Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, _Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ReadExtensions = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, ReadExtensions(ReadExtensions, false)),\n                    smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                    receive\n                        {tcp, CSock, _} -> ok\n                    end,\n                    {ok, Socket} = smtp_socket:to_ssl_client(CSock),\n                    smtp_socket:active_once(Socket),\n                    smtp_socket:send(Socket, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {ssl, Socket, PacketN} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", PacketN),\n                    Bar = fun(F, Acc) ->\n                        receive\n                            {ssl, Socket, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, true);\n                            {ssl, Socket, \"250-\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, Acc);\n                            {ssl, Socket, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                true;\n                            {ssl, Socket, \"250 \" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                Acc;\n                            {tcp, Socket, _} ->\n                                smtp_socket:active_once(Socket),\n                                error\n                        end\n                    end,\n                    ?assertEqual(false, Bar(Bar, false)),\n                    smtp_socket:send(Socket, \"STARTTLS\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet6} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"500 \" ++ _, Packet6)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"STARTTLS can't take any parameters\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"STARTTLS foo\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> ok\n                    end,\n                    ?assertMatch(\"501 \" ++ _, Packet4)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"After STARTTLS, message is received by server\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, _Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, _Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ReadExtensions = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-\" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 \" ++ _Packet3} ->\n                                smtp_socket:active_once(CSock),\n                                Acc;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, ReadExtensions(ReadExtensions, false)),\n                    smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                    receive\n                        {tcp, CSock, _} -> ok\n                    end,\n                    {ok, Socket} = smtp_socket:to_ssl_client(CSock),\n                    smtp_socket:active_once(Socket),\n                    smtp_socket:send(Socket, \"EHLO somehost.com\\r\\n\"),\n                    ReadSSLExtensions = fun(F, Acc) ->\n                        receive\n                            {ssl, Socket, \"250-\" ++ _Rest} ->\n                                smtp_socket:active_once(Socket),\n                                F(F, Acc);\n                            {ssl, Socket, \"250 \" ++ _} ->\n                                smtp_socket:active_once(Socket),\n                                true;\n                            {ssl, Socket, _R} ->\n                                smtp_socket:active_once(Socket),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, ReadSSLExtensions(ReadSSLExtensions, false)),\n                    smtp_socket:send(Socket, \"MAIL FROM:<user@somehost.com>\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet4} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(Socket, \"RCPT TO:<user@otherhost.com>\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet5} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet5),\n                    smtp_socket:send(Socket, \"DATA\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet6} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet6),\n                    smtp_socket:send(Socket, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(Socket, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(Socket, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(Socket, \"\\r\\n\"),\n                    smtp_socket:send(Socket, \"message body\"),\n                    smtp_socket:send(Socket, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {ssl, Socket, Packet7} -> smtp_socket:active_once(Socket)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet7)\n                end}\n            end\n        ]}.\n\nsmtp_session_tls_sni_test_() ->\n    {foreach, local,\n        fun() ->\n            SniHosts =\n                [\n                    {\"mx1.example.com\", [\n                        {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                        {certfile, \"test/fixtures/mx1.example.com-server.crt\"},\n                        {cacertfile, \"test/fixtures/root.crt\"}\n                    ]},\n                    {\"mx2.example.com\", [\n                        {keyfile, \"test/fixtures/mx2.example.com-server.key\"},\n                        {certfile, \"test/fixtures/mx2.example.com-server.crt\"},\n                        {cacertfile, \"test/fixtures/root.crt\"}\n                    ]}\n                ],\n            application:ensure_all_started(gen_smtp),\n            {ok, _} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [\n                        {tls_options, [{sni_hosts, SniHosts}]},\n                        {callbackoptions, [{auth, true}]}\n                    ]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            [Host || {Host, _} <- SniHosts]\n        end,\n        fun(_Hosts) ->\n            gen_smtp_server:stop(gen_smtp_server)\n        end,\n        [fun strict_sni/1]}.\n\nstrict_sni(Hosts) ->\n    {\"Do strict validation based on SNI\", fun() ->\n        [\n            begin\n                {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n                smtp_socket:active_once(CSock),\n                receive\n                    {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                end,\n                ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                receive\n                    {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                end,\n                ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                Foo = fun Foo(Acc) ->\n                    receive\n                        {tcp, CSock, \"250-STARTTLS\" ++ _} ->\n                            smtp_socket:active_once(CSock),\n                            Foo(true);\n                        {tcp, CSock, \"250-\" ++ _Packet3} ->\n                            smtp_socket:active_once(CSock),\n                            Foo(Acc);\n                        {tcp, CSock, \"250 STARTTLS\" ++ _} ->\n                            smtp_socket:active_once(CSock),\n                            true;\n                        {tcp, CSock, \"250 \" ++ _Packet3} ->\n                            smtp_socket:active_once(CSock),\n                            Acc;\n                        {tcp, CSock, _} ->\n                            smtp_socket:active_once(CSock),\n                            error\n                    end\n                end,\n                ?assertEqual(true, Foo(false)),\n                smtp_socket:send(CSock, \"STARTTLS\\r\\n\"),\n                receive\n                    {tcp, CSock, Packet4} -> ok\n                end,\n                ?assertMatch(\"220 \" ++ _, Packet4),\n                {ok, TlsSocket} = ssl:connect(\n                    CSock,\n                    [\n                        {server_name_indication, Host},\n                        {verify, verify_peer},\n                        {cacertfile, \"test/fixtures/root.crt\"}\n                    ]\n                ),\n                %% Make sure server selects certificate based on SNI\n                {ok, Cert} = ssl:peercert(TlsSocket),\n                verify_cert_hostname(Cert, Host),\n                smtp_socket:active_once(TlsSocket),\n                smtp_socket:send(TlsSocket, \"EHLO somehost.com\\r\\n\"),\n                receive\n                    {ssl, TlsSocket, Packet5} -> smtp_socket:active_once(TlsSocket)\n                end,\n                ?assertMatch(\"250-localhost\\r\\n\", Packet5),\n                ssl:close(TlsSocket)\n            end\n         || Host <- Hosts\n        ]\n    end}.\n\nverify_cert_hostname(BinCert, Host) ->\n    DecCert = public_key:pkix_decode_cert(BinCert, otp),\n    ?assert(public_key:pkix_verify_hostname(DecCert, [{dns_id, Host}])).\n\nstray_newline_test_() ->\n    [\n        {\"Error out by default\", fun() ->\n            ?assertEqual(<<\"foo\">>, check_bare_crlf(<<\"foo\">>, <<>>, false, 0)),\n            ?assertEqual(error, check_bare_crlf(<<\"foo\\n\">>, <<>>, false, 0)),\n            ?assertEqual(error, check_bare_crlf(<<\"fo\\ro\\n\">>, <<>>, false, 0)),\n            ?assertEqual(error, check_bare_crlf(<<\"fo\\ro\\n\\r\">>, <<>>, false, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"foo\\r\\n\">>, <<>>, false, 0)),\n            ?assertEqual(<<\"foo\\r\">>, check_bare_crlf(<<\"foo\\r\">>, <<>>, false, 0))\n        end},\n        {\"Fixing them should work\", fun() ->\n            ?assertEqual(<<\"foo\">>, check_bare_crlf(<<\"foo\">>, <<>>, fix, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"foo\\n\">>, <<>>, fix, 0)),\n            ?assertEqual(<<\"fo\\r\\no\\r\\n\">>, check_bare_crlf(<<\"fo\\ro\\n\">>, <<>>, fix, 0)),\n            ?assertEqual(<<\"fo\\r\\no\\r\\n\\r\">>, check_bare_crlf(<<\"fo\\ro\\n\\r\">>, <<>>, fix, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"foo\\r\\n\">>, <<>>, fix, 0))\n        end},\n        {\"Stripping them should work\", fun() ->\n            ?assertEqual(<<\"foo\">>, check_bare_crlf(<<\"foo\">>, <<>>, strip, 0)),\n            ?assertEqual(<<\"foo\">>, check_bare_crlf(<<\"fo\\ro\\n\">>, <<>>, strip, 0)),\n            ?assertEqual(<<\"foo\\r\">>, check_bare_crlf(<<\"fo\\ro\\n\\r\">>, <<>>, strip, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"foo\\r\\n\">>, <<>>, strip, 0))\n        end},\n        {\"Ignoring them should work\", fun() ->\n            ?assertEqual(<<\"foo\">>, check_bare_crlf(<<\"foo\">>, <<>>, ignore, 0)),\n            ?assertEqual(<<\"fo\\ro\\n\">>, check_bare_crlf(<<\"fo\\ro\\n\">>, <<>>, ignore, 0)),\n            ?assertEqual(<<\"fo\\ro\\n\\r\">>, check_bare_crlf(<<\"fo\\ro\\n\\r\">>, <<>>, ignore, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"foo\\r\\n\">>, <<>>, ignore, 0))\n        end},\n        {\"Leading bare LFs should check the previous line\", fun() ->\n            ?assertEqual(<<\"\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\">>, false, 0)),\n            ?assertEqual(\n                <<\"\\r\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\\n\">>, fix, 0)\n            ),\n            ?assertEqual(<<\"\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\">>, fix, 0)),\n            ?assertEqual(<<\"foo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\\n\">>, strip, 0)),\n            ?assertEqual(<<\"\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\">>, strip, 0)),\n            ?assertEqual(\n                <<\"\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\\n\">>, ignore, 0)\n            ),\n            ?assertEqual(error, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\\n\">>, false, 0)),\n            ?assertEqual(<<\"\\nfoo\\r\\n\">>, check_bare_crlf(<<\"\\nfoo\\r\\n\">>, <<\"bar\\r\">>, false, 0))\n        end}\n    ].\n\nsmtp_session_maxsize_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [{callbackoptions, [{size, 100}]}]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"Message with ok size\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE 100\\r\\n\"} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-SIZE\" ++ _} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<test@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"message body\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet7} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet7)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Message with too large size\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE 100\\r\\n\"} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-SIZE\" ++ _} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<test@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(\n                        CSock, \"message body message body message body message body message body\"\n                    ),\n                    smtp_socket:send(\n                        CSock, \"message body message body message body message body message body\"\n                    ),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet7} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"552 \" ++ _, Packet7)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Message with ok size in FROM extension\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE 100\\r\\n\"} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-SIZE\" ++ _} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost> SIZE=100\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Message with not ok size in FROM extension\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE 100\\r\\n\"} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-SIZE\" ++ _} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost> SIZE=101\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"552 \" ++ _, Packet3)\n                end}\n            end\n        ]}.\n\nsmtp_session_nomaxsize_test_() ->\n    {foreach, local,\n        fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, Pid} = gen_smtp_server:start(\n                smtp_server_example,\n                [\n                    {sessionoptions, [{callbackoptions, [{size, infinity}]}]},\n                    {domain, \"localhost\"},\n                    {port, 9876}\n                ]\n            ),\n            {ok, CSock} = smtp_socket:connect(tcp, \"localhost\", 9876),\n            {CSock, Pid}\n        end,\n        fun({CSock, _Pid}) ->\n            gen_smtp_server:stop(gen_smtp_server),\n            smtp_socket:close(CSock),\n            timer:sleep(10)\n        end,\n        [\n            fun({CSock, _Pid}) ->\n                {\"Message with no max size\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE\" ++ _ = _Data} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _Data} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3),\n                    smtp_socket:send(CSock, \"RCPT TO:<test@somehost.com>\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet4} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet4),\n                    smtp_socket:send(CSock, \"DATA\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet5} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"354 \" ++ _, Packet5),\n                    smtp_socket:send(CSock, \"Subject: tls message\\r\\n\"),\n                    smtp_socket:send(CSock, \"To: <user@otherhost>\\r\\n\"),\n                    smtp_socket:send(CSock, \"From: <user@somehost.com>\\r\\n\"),\n                    smtp_socket:send(CSock, \"\\r\\n\"),\n                    smtp_socket:send(CSock, \"message body\"),\n                    smtp_socket:send(CSock, \"\\r\\n.\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet7} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet7)\n                end}\n            end,\n            fun({CSock, _Pid}) ->\n                {\"Message with ok huge size in FROM extension\", fun() ->\n                    smtp_socket:active_once(CSock),\n                    receive\n                        {tcp, CSock, Packet} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"220 localhost\" ++ _Stuff, Packet),\n                    smtp_socket:send(CSock, \"EHLO somehost.com\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet2} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250-localhost\\r\\n\", Packet2),\n                    Foo = fun(F, Acc) ->\n                        receive\n                            {tcp, CSock, \"250-SIZE 100\\r\\n\"} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, true);\n                            {tcp, CSock, \"250-SIZE\" ++ _} ->\n                                error;\n                            {tcp, CSock, \"250-\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                F(F, Acc);\n                            {tcp, CSock, \"250 PIPELINING\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, \"250 SMTPUTF8\" ++ _} ->\n                                smtp_socket:active_once(CSock),\n                                true;\n                            {tcp, CSock, _} ->\n                                smtp_socket:active_once(CSock),\n                                error\n                        end\n                    end,\n                    ?assertEqual(true, Foo(Foo, false)),\n                    smtp_socket:send(CSock, \"MAIL FROM:<user@otherhost> SIZE=100000000\\r\\n\"),\n                    receive\n                        {tcp, CSock, Packet3} -> smtp_socket:active_once(CSock)\n                    end,\n                    ?assertMatch(\"250 \" ++ _, Packet3)\n                end}\n            end\n        ]}.\n\n-endif.\n"
  },
  {
    "path": "src/mimemail.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc A module for decoding/encoding MIME 1.0 email.\n%% The encoder and decoder operate on the same data structure, which is as follows:\n%% A 5-tuple with the following elements: `{Type, SubType, Headers, Parameters, Body}'.\n%%\n%% `Type' and `SubType' are the MIME type of the email, examples are `text/plain' or\n%% `multipart/alternative'. The decoder splits these into 2 fields so you can filter by\n%% the main type or by the subtype.\n%%\n%% `Headers' consists of a list of key/value pairs of binary values eg.\n%% `{<<\"From\">>, <<\"Andrew Thompson <andrew@hijacked.us>\">>}'. There is no parsing of\n%% the header aside from un-wrapping the lines and splitting the header name from the\n%% header value.\n%%\n%% `Parameters' is a list of 3 key/value tuples. The 3 keys are `<<\"content-type-params\">>',\n%% `<<\"disposition\">>' and `<<\"disposition-params\">>'.\n%% `content-type-params' is a key/value list of parameters on the content-type header, this\n%% usually consists of things like charset and the format parameters. `disposition' indicates\n%% how the data wants to be displayed, this is usually 'inline'. `disposition-params' is a list of\n%% disposition information, eg. the filename this section should be saved as, the modification\n%% date the file should be saved with, etc.\n%%\n%% Finally, `Body' can be one of several different types, depending on the structure of the email.\n%% For a simple email, the body will usually be a binary consisting of the message body, In the\n%% case of a multipart email, its a list of these 5-tuple MIME structures. The third possibility,\n%% in the case of a message/rfc822 attachment, body can be a single 5-tuple MIME structure.\n%%\n%% You should see the relevant RFCs (2045, 2046, 2047, etc.) for more information.\n%%\n%% Note that parts of this module (e.g., `decode/2') use the\n%% <a href=\"https://hex.pm/packages/iconv\"><tt>iconv</tt></a> library for string conversion,\n%% which you will need to explicitly list as a dependency.\n\n-module(mimemail).\n\n-ifdef(TEST).\n-include_lib(\"eunit/include/eunit.hrl\").\n-export([rfc2047_utf8_encode/1]).\n-endif.\n\n-export([encode/1, encode/2, decode/2, decode/1, get_header_value/2, get_header_value/3, parse_headers/1]).\n-export([encode_quoted_printable/1, decode_quoted_printable/1]).\n\n-export_type([\n    mimetuple/0,\n    mime_type/0,\n    mime_subtype/0,\n    headers/0,\n    parameters/0,\n    options/0,\n    dkim_options/0\n]).\n\n-include_lib(\"kernel/include/logger.hrl\").\n\n-define(LOGGER_META, #{domain => [gen_smtp]}).\n\n-define(DEFAULT_MIME_VERSION, <<\"1.0\">>).\n\n-define(DEFAULT_OPTIONS, [\n    % default encoding is utf-8 if we can find the iconv module\n    {encoding, get_default_encoding()},\n    % should we decode any base64/quoted printable attachments?\n    {decode_attachments, true},\n    % should we assume default mime version\n    {allow_missing_version, true},\n    % default mime version\n    {default_mime_version, ?DEFAULT_MIME_VERSION}\n]).\n\n% `<<\"text\">>'\n-type mime_type() :: binary().\n% `<<\"plain\">>'\n-type mime_subtype() :: binary().\n% `[{<<\"Content-Type\">>, <<\"text/plain\">>}]'\n-type headers() :: [{binary(), binary()}].\n-type parameters() ::\n    %% <<\"7bit\">> | <<\"base64\">> | <<\"quoted-printable\">> etc\n    #{\n        transfer_encoding => binary(),\n        %% [{<<\"charset\">>, <<\"utf-8\">>} | {<<\"boundary\">>, binary()} | {<<\"name\">>, binary()} etc...]\n        content_type_params => [{binary(), binary()}],\n        %% <<\"inline\">> | <<\"attachment\">> etc...\n        disposition => binary(),\n        %% [{<<\"filename\">>, binary()}, ]\n        disposition_params => [{binary(), binary()}]\n    }.\n\n-type mimetuple() :: {\n    mime_type(),\n    mime_subtype(),\n    headers(),\n    parameters(),\n    Body :: binary() | mimetuple() | [mimetuple()]\n}.\n\n-type dkim_priv_key() ::\n    {pem_plain, binary()}\n    | {pem_encrypted, Key :: binary(), Passwd :: string()}.\n-type dkim_options() :: [\n    {h, [binary()]}\n    | {d, binary()}\n    | {s, binary()}\n    | {t, now | calendar:datetime()}\n    | {x, calendar:datetime()}\n    | {c, {simple | relaxed, simple | relaxed}}\n    | {a, 'rsa-sha256' | 'ed25519-sha256'}\n    | {private_key, dkim_priv_key()}\n].\n-type options() :: [\n    {encoding, binary()}\n    | {decode_attachment, boolean()}\n    | {dkim, dkim_options()}\n    | {allow_missing_version, boolean()}\n    | {default_mime_version, binary()}\n].\n\n-spec decode(Email :: binary()) -> mimetuple().\n%% @doc Decode a MIME email from a binary.\ndecode(All) ->\n    {Headers, Body} = parse_headers(All),\n    decode(Headers, Body, ?DEFAULT_OPTIONS).\n\n-spec decode(Email :: binary(), Options :: options()) -> mimetuple().\n%% @doc Decode with custom options\ndecode(All, Options) when is_binary(All), is_list(Options) ->\n    {Headers, Body} = parse_headers(All),\n    decode(Headers, Body, Options).\n\ndecode(OrigHeaders, Body, Options) ->\n    ?LOG_DEBUG(\"headers: ~p\", [OrigHeaders], ?LOGGER_META),\n    Encoding = proplists:get_value(encoding, Options, none),\n    %FixedHeaders = fix_headers(Headers),\n    Headers = decode_headers(OrigHeaders, [], Encoding),\n    case parse_with_comments(get_header_value(<<\"MIME-Version\">>, Headers)) of\n        undefined ->\n            AllowMissingVersion = proplists:get_value(allow_missing_version, Options, false),\n            case parse_content_type(get_header_value(<<\"Content-Type\">>, Headers)) of\n                {<<\"multipart\">>, _SubType, _Parameters} when AllowMissingVersion ->\n                    MimeVersion = proplists:get_value(default_mime_version, Options, ?DEFAULT_MIME_VERSION),\n                    decode_component(Headers, Body, MimeVersion, Options);\n                {<<\"multipart\">>, _SubType, _Parameters} ->\n                    erlang:error(non_mime_multipart);\n                {Type, SubType, CTParameters} ->\n                    NewBody = decode_body(\n                        get_header_value(<<\"Content-Transfer-Encoding\">>, Headers),\n                        Body,\n                        proplists:get_value(<<\"charset\">>, CTParameters),\n                        Encoding\n                    ),\n                    {Disposition, DispositionParams} =\n                        case parse_content_disposition(get_header_value(<<\"Content-Disposition\">>, Headers)) of\n                            undefined ->\n                                {<<\"inline\">>, []};\n                            Disp ->\n                                Disp\n                        end,\n                    Parameters = #{\n                        content_type_params => CTParameters,\n                        disposition => Disposition,\n                        disposition_params => DispositionParams\n                    },\n                    {Type, SubType, Headers, Parameters, NewBody};\n                undefined ->\n                    Parameters = #{\n                        content_type_params => [{<<\"charset\">>, <<\"us-ascii\">>}],\n                        disposition => <<\"inline\">>,\n                        disposition_params => []\n                    },\n                    {<<\"text\">>, <<\"plain\">>, Headers, Parameters,\n                        decode_body(get_header_value(<<\"Content-Transfer-Encoding\">>, Headers), Body)}\n            end;\n        Other ->\n            decode_component(Headers, Body, Other, Options)\n    end.\n\n-spec encode(MimeMail :: mimetuple()) -> binary().\nencode(MimeMail) ->\n    encode(MimeMail, []).\n\n%% @doc Encode a MIME tuple to a binary.\nencode({Type, Subtype, Headers, ContentTypeParams, Parts}, Options) ->\n    {FixedParams, FixedHeaders} = ensure_content_headers(Type, Subtype, ContentTypeParams, Headers, Parts, true),\n    CheckedHeaders = check_headers(FixedHeaders),\n    EncodedBody = binstr:join(\n        encode_component(Type, Subtype, CheckedHeaders, FixedParams, Parts),\n        \"\\r\\n\"\n    ),\n    EncodedHeaders = encode_headers(CheckedHeaders),\n    SignedHeaders =\n        case proplists:get_value(dkim, Options) of\n            undefined -> EncodedHeaders;\n            DKIM -> dkim_sign_email(EncodedHeaders, EncodedBody, DKIM)\n        end,\n    list_to_binary([\n        binstr:join(SignedHeaders, \"\\r\\n\"),\n        \"\\r\\n\\r\\n\",\n        EncodedBody\n    ]);\nencode(_, _) ->\n    ?LOG_DEBUG(\"Not a mime-decoded DATA\", ?LOGGER_META),\n    erlang:error(non_mime).\n\ndecode_headers(Headers, _, none) ->\n    Headers;\ndecode_headers([], Acc, _Charset) ->\n    lists:reverse(Acc);\ndecode_headers([{Key, Value} | Headers], Acc, Charset) ->\n    decode_headers(Headers, [{Key, decode_header(Value, Charset)} | Acc], Charset).\n\ndecode_header(Value, Charset) ->\n    RTokens = tokenize_header(Value, []),\n    Tokens = lists:reverse(RTokens),\n    Decoded =\n        try\n            decode_header_tokens_strict(Tokens, Charset)\n        catch\n            Type:Reason:Stacktrace ->\n                case decode_header_tokens_permissive(Tokens, Charset, []) of\n                    {ok, Dec} ->\n                        Dec;\n                    error ->\n                        % re-throw original error\n                        erlang:raise(Type, Reason, Stacktrace)\n                end\n        end,\n    iolist_to_binary(Decoded).\n\n-type hdr_token() :: binary() | {Encoding :: binary(), Data :: binary()}.\n-spec tokenize_header(binary(), [hdr_token()]) -> [hdr_token()].\ntokenize_header(<<>>, Acc) ->\n    Acc;\ntokenize_header(Value, Acc) ->\n    %% maybe replace \"?([^\\s]+)\\\\?\" with \"?([^\\s]*)\\\\?\"?\n    %% see msg lvuvmm593b8s7pqqfhu7cdtqd4g4najh\n    %% Subject: =?utf-8?Q??=\n    %%\t=?utf-8?Q?=D0=9F=D0=BE=D0=B4=D1=82=D0=B2=D0=B5=D1=80=D0=B4=D0=B8=D1=82=D0=B5=20?=\n    %%\t=?utf-8?Q?=D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D1=8E=20?=\n    %%\t=?utf-8?Q?=D0=B2=20Moy-Rebenok.ru?=\n\n    case re:run(Value, \"=\\\\?([-A-Za-z0-9_]+)\\\\?([qQbB])\\\\?([^\\s]+)\\\\?=\", [ungreedy]) of\n        nomatch ->\n            [Value | Acc];\n        {match, [{AllStart, AllLen}, {EncodingStart, EncodingLen}, {TypeStart, _}, {DataStart, DataLen}]} ->\n            %% RFC 2047 #2 (encoded-word)\n            Encoding = binstr:substr(Value, EncodingStart + 1, EncodingLen),\n            Type = binstr:to_lower(binstr:substr(Value, TypeStart + 1, 1)),\n            Data = binstr:substr(Value, DataStart + 1, DataLen),\n\n            EncodedData =\n                case Type of\n                    <<\"q\">> ->\n                        %% RFC 2047 #5. (3)\n                        decode_quoted_printable(binary:replace(Data, <<\"_\">>, <<\"=20\">>, [global]));\n                    <<\"b\">> ->\n                        decode_base64(binary:replace(Data, <<\"_\">>, <<\" \">>, [global]))\n                end,\n\n            Offset =\n                case\n                    re:run(\n                        binstr:substr(Value, AllStart + AllLen + 1),\n                        \"^([\\s\\t\\n\\r]+)=\\\\?[-A-Za-z0-9_]+\\\\?[^\\s]\\\\?[^\\s]+\\\\?=\",\n                        [ungreedy]\n                    )\n                of\n                    nomatch ->\n                        % no 2047 block immediately following\n                        1;\n                    {match, [{_, _}, {_, WhiteSpaceLen}]} ->\n                        1 + WhiteSpaceLen\n                end,\n\n            NewAcc =\n                case binstr:substr(Value, 1, AllStart) of\n                    <<>> -> [{fix_encoding(Encoding), EncodedData} | Acc];\n                    Other -> [{fix_encoding(Encoding), EncodedData}, Other | Acc]\n                end,\n            tokenize_header(binstr:substr(Value, AllStart + AllLen + Offset), NewAcc)\n    end.\n\ndecode_header_tokens_strict([], _) ->\n    [];\ndecode_header_tokens_strict([{Encoding, Data} | Tokens], Charset) ->\n    {ok, S} = convert(Charset, Encoding, Data),\n    [S | decode_header_tokens_strict(Tokens, Charset)];\ndecode_header_tokens_strict([Data | Tokens], Charset) ->\n    [Data | decode_header_tokens_strict(Tokens, Charset)].\n\n%% this decoder can handle folded not-by-RFC UTF headers, when somebody split\n%% multibyte string not by characters, but by bytes. It first join folded\n%% string and only then decode it with iconv.\ndecode_header_tokens_permissive([], _, [Result]) when is_binary(Result) ->\n    {ok, Result};\ndecode_header_tokens_permissive([], _, Stack) ->\n    case lists:all(fun erlang:is_binary/1, Stack) of\n        true -> {ok, lists:reverse(Stack)};\n        false -> error\n    end;\ndecode_header_tokens_permissive([{Enc, Data} | Tokens], Charset, [{Enc, PrevData} | Stack]) ->\n    NewData = iolist_to_binary([PrevData, Data]),\n    {ok, S} = convert(Charset, Enc, NewData),\n    decode_header_tokens_permissive(Tokens, Charset, [S | Stack]);\ndecode_header_tokens_permissive([NextToken | _] = Tokens, Charset, [{_, _} | Stack]) when\n    is_binary(NextToken) orelse is_tuple(NextToken)\n->\n    %% practically very rare case \"=?utf-8?Q?BROKEN?=\\r\\n\\t=?windows-1251?Q?maybe-broken?=\"\n    %% or \"=?utf-8?Q?BROKEN?= raw-ascii-string\"\n    %% drop broken value from stack\n    decode_header_tokens_permissive(Tokens, Charset, Stack);\ndecode_header_tokens_permissive([Data | Tokens], Charset, Stack) ->\n    decode_header_tokens_permissive(Tokens, Charset, [Data | Stack]).\n\n%% x-binaryenc is not a real encoding and is not used for text, so let it pass through\nconvert(_To, <<\"x-binaryenc\">>, Data) ->\n    {ok, Data};\nconvert(To, From, Data) ->\n    Result = iconv:convert(From, To, Data),\n    {ok, Result}.\n\ndecode_component(Headers, Body, MimeVsn = <<\"1.0\", _/binary>>, Options) ->\n    case parse_content_disposition(get_header_value(<<\"Content-Disposition\">>, Headers)) of\n        {Disposition, DispositionParams} ->\n            ok;\n        % defaults\n        _ ->\n            Disposition = <<\"inline\">>,\n            DispositionParams = []\n    end,\n\n    case parse_content_type(get_header_value(<<\"Content-Type\">>, Headers)) of\n        {<<\"multipart\">>, SubType, Parameters} ->\n            case proplists:get_value(<<\"boundary\">>, Parameters) of\n                undefined ->\n                    erlang:error(no_boundary);\n                Boundary ->\n                    ?LOG_DEBUG(\n                        \"this is a multipart email of type:  ~s and boundary ~s\", [SubType, Boundary], ?LOGGER_META\n                    ),\n                    Parameters2 = #{\n                        content_type_params => Parameters,\n                        disposition => Disposition,\n                        disposition_params => DispositionParams\n                    },\n                    {<<\"multipart\">>, SubType, Headers, Parameters2,\n                        split_body_by_boundary(Body, list_to_binary([\"--\", Boundary]), MimeVsn, Options)}\n            end;\n        {<<\"message\">>, <<\"rfc822\">>, Parameters} ->\n            {NewHeaders, NewBody} = parse_headers(Body),\n            Parameters2 = #{\n                content_type_params => Parameters,\n                disposition => Disposition,\n                disposition_params => DispositionParams\n            },\n            {<<\"message\">>, <<\"rfc822\">>, Headers, Parameters2, decode(NewHeaders, NewBody, Options)};\n        {Type, SubType, Parameters} ->\n            ?LOG_DEBUG(\"body is ~s/~s\", [Type, SubType], ?LOGGER_META),\n            Parameters2 = #{\n                content_type_params => Parameters,\n                disposition => Disposition,\n                disposition_params => DispositionParams\n            },\n            {Type, SubType, Headers, Parameters2,\n                decode_body(\n                    get_header_value(<<\"Content-Transfer-Encoding\">>, Headers),\n                    Body,\n                    proplists:get_value(<<\"charset\">>, Parameters),\n                    proplists:get_value(encoding, Options, none)\n                )};\n        % defaults\n        undefined ->\n            Type = <<\"text\">>,\n            SubType = <<\"plain\">>,\n            Parameters = #{\n                content_type_params => [{<<\"charset\">>, <<\"us-ascii\">>}],\n                disposition => Disposition,\n                disposition_params => DispositionParams\n            },\n            {Type, SubType, Headers, Parameters,\n                decode_body(get_header_value(<<\"Content-Transfer-Encoding\">>, Headers), Body)}\n    end;\ndecode_component(_Headers, _Body, Other, _Options) ->\n    erlang:error({mime_version, Other}).\n\n-spec get_header_value(Needle :: binary(), Headers :: [{binary(), binary()}], Default :: any()) -> binary() | any().\n%% @doc Do a case-insensitive header lookup to return that header's value, or the specified default.\nget_header_value(Needle, Headers, Default) ->\n    ?LOG_DEBUG(\"Headers: ~p\", [Headers], ?LOGGER_META),\n    NeedleLower = binstr:to_lower(Needle),\n    F =\n        fun({Header, _Value}) ->\n            binstr:to_lower(Header) =:= NeedleLower\n        end,\n    case lists:search(F, Headers) of\n        % TODO if there's duplicate headers, should we use the first or the last?\n        {value, {_Header, Value}} ->\n            Value;\n        false ->\n            Default\n    end.\n\n-spec get_header_value(Needle :: binary(), Headers :: [{binary(), binary()}]) -> binary() | 'undefined'.\n%% @doc Do a case-insensitive header lookup to return the header's value, or `undefined'.\nget_header_value(Needle, Headers) ->\n    get_header_value(Needle, Headers, undefined).\n\n-spec parse_with_comments\n    (Value :: binary()) -> binary() | no_return();\n    (Value :: atom()) -> atom().\nparse_with_comments(Value) when is_binary(Value) ->\n    parse_with_comments(Value, [], 0, false);\nparse_with_comments(Value) ->\n    Value.\n\n-spec parse_with_comments(Value :: binary(), Acc :: list(), Depth :: non_neg_integer(), Quotes :: boolean()) ->\n    binary() | no_return().\nparse_with_comments(<<>>, _Acc, _Depth, Quotes) when Quotes ->\n    erlang:error(unterminated_quotes);\nparse_with_comments(<<>>, _Acc, Depth, _Quotes) when Depth > 0 ->\n    erlang:error(unterminated_comment);\nparse_with_comments(<<>>, Acc, _Depth, _Quotes) ->\n    binstr:strip(list_to_binary(lists:reverse(Acc)));\nparse_with_comments(<<$\\\\, H, Tail/binary>>, Acc, Depth, Quotes) when Depth > 0, H > 32, H < 127 ->\n    parse_with_comments(Tail, Acc, Depth, Quotes);\nparse_with_comments(<<$\\\\, Tail/binary>>, Acc, Depth, Quotes) when Depth > 0 ->\n    parse_with_comments(Tail, Acc, Depth, Quotes);\nparse_with_comments(<<$\\\\, H, Tail/binary>>, Acc, Depth, Quotes) when H > 32, H < 127 ->\n    parse_with_comments(Tail, [H | Acc], Depth, Quotes);\nparse_with_comments(<<$\\\\, Tail/binary>>, Acc, Depth, Quotes) ->\n    parse_with_comments(Tail, [$\\\\ | Acc], Depth, Quotes);\nparse_with_comments(<<$(, Tail/binary>>, Acc, Depth, Quotes) when not Quotes ->\n    parse_with_comments(Tail, Acc, Depth + 1, Quotes);\nparse_with_comments(<<$), Tail/binary>>, Acc, Depth, Quotes) when Depth > 0, not Quotes ->\n    parse_with_comments(Tail, Acc, Depth - 1, Quotes);\nparse_with_comments(<<_, Tail/binary>>, Acc, Depth, Quotes) when Depth > 0 ->\n    parse_with_comments(Tail, Acc, Depth, Quotes);\n%\"\nparse_with_comments(<<$\", T/binary>>, Acc, Depth, true) ->\n    parse_with_comments(T, Acc, Depth, false);\n%\"\nparse_with_comments(<<$\", T/binary>>, Acc, Depth, false) ->\n    parse_with_comments(T, Acc, Depth, true);\nparse_with_comments(<<H, Tail/binary>>, Acc, Depth, Quotes) ->\n    parse_with_comments(Tail, [H | Acc], Depth, Quotes).\n\n-spec parse_content_type\n    (Value :: 'undefined') -> 'undefined';\n    (Value :: binary()) -> {binary(), binary(), [{binary(), binary()}]}.\nparse_content_type(undefined) ->\n    undefined;\nparse_content_type(String) ->\n    try parse_content_disposition(String) of\n        {RawType, Parameters} ->\n            case binstr:strchr(RawType, $/) of\n                Index when Index < 2 ->\n                    throw(bad_content_type);\n                Index ->\n                    Type = binstr:substr(RawType, 1, Index - 1),\n                    SubType = binstr:substr(RawType, Index + 1),\n                    {binstr:to_lower(Type), binstr:to_lower(SubType), Parameters}\n            end\n    catch\n        bad_disposition ->\n            throw(bad_content_type)\n    end.\n\n-spec parse_content_disposition\n    (Value :: 'undefined') -> 'undefined';\n    (String :: binary()) -> {binary(), [{binary(), binary()}]}.\nparse_content_disposition(undefined) ->\n    undefined;\nparse_content_disposition(String) ->\n    [Disposition | Parameters] = binstr:split(parse_with_comments(String), <<\";\">>),\n    F =\n        fun(X) ->\n            Y = binstr:strip(binstr:strip(X), both, $\\t),\n            case binstr:strchr(Y, $=) of\n                Index when Index < 2 ->\n                    throw(bad_disposition);\n                Index ->\n                    Key = binstr:substr(Y, 1, Index - 1),\n                    Value = binstr:substr(Y, Index + 1),\n                    {binstr:to_lower(Key), Value}\n            end\n        end,\n    Params = lists:map(F, Parameters),\n    {binstr:to_lower(Disposition), Params}.\n\nsplit_body_by_boundary(Body, Boundary, MimeVsn, Options) ->\n    % find the indices of the first and last boundary\n    case {binstr:strpos(Body, Boundary), binstr:strpos(Body, list_to_binary([Boundary, \"--\"]))} of\n        {0, _} ->\n            erlang:error(missing_boundary);\n        {_, 0} ->\n            erlang:error(missing_last_boundary);\n        {Start, End} ->\n            NewBody = binstr:substr(Body, Start + byte_size(Boundary), End - Start),\n            % from now on, we can be sure that each boundary is preceded by a CRLF\n            Parts = split_body_by_boundary_(NewBody, list_to_binary([\"\\r\\n\", Boundary]), [], Options),\n            [\n                decode_component(Headers, Body2, MimeVsn, Options)\n             || {Headers, Body2} <- [V || {_, Body3} = V <- Parts, byte_size(Body3) =/= 0]\n            ]\n    end.\n\nsplit_body_by_boundary_(<<>>, _Boundary, Acc, _Options) ->\n    lists:reverse(Acc);\nsplit_body_by_boundary_(Body, Boundary, Acc, Options) ->\n    % trim the incomplete first line\n    TrimmedBody = binstr:substr(Body, binstr:strpos(Body, \"\\r\\n\") + 2),\n    case binstr:strpos(TrimmedBody, Boundary) of\n        0 ->\n            lists:reverse([{[], TrimmedBody} | Acc]);\n        Index ->\n            {ParsedHdrs, BodyRest} = parse_headers(binstr:substr(TrimmedBody, 1, Index - 1)),\n            DecodedHdrs = decode_headers(ParsedHdrs, [], proplists:get_value(encoding, Options, none)),\n            split_body_by_boundary_(\n                binstr:substr(TrimmedBody, Index + byte_size(Boundary)),\n                Boundary,\n                [{DecodedHdrs, BodyRest} | Acc],\n                Options\n            )\n    end.\n\n-spec parse_headers(Body :: binary()) -> {[{binary(), binary()}], binary()}.\n%% @doc Parse the headers off of a message and return a list of headers and the trailing body.\nparse_headers(Body) ->\n    case binstr:strpos(Body, \"\\r\\n\") of\n        0 ->\n            {[], Body};\n        1 ->\n            {[], binstr:substr(Body, 3)};\n        Index ->\n            parse_headers(binstr:substr(Body, Index + 2), binstr:substr(Body, 1, Index - 1), [])\n    end.\n\nparse_headers(Body, <<H, Tail/binary>>, []) when H =:= $\\s; H =:= $\\t ->\n    % folded headers\n    {[], list_to_binary([H, Tail, \"\\r\\n\", Body])};\nparse_headers(Body, <<H, T/binary>>, Headers) when H =:= $\\s; H =:= $\\t ->\n    % folded headers\n    [{FieldName, OldFieldValue} | OtherHeaders] = Headers,\n    FieldValue = list_to_binary([OldFieldValue, T]),\n    ?LOG_DEBUG(\"~p = ~p\", [FieldName, FieldValue], ?LOGGER_META),\n    case binstr:strpos(Body, \"\\r\\n\") of\n        0 ->\n            {lists:reverse([{FieldName, FieldValue} | OtherHeaders]), Body};\n        1 ->\n            {lists:reverse([{FieldName, FieldValue} | OtherHeaders]), binstr:substr(Body, 3)};\n        Index2 ->\n            parse_headers(binstr:substr(Body, Index2 + 2), binstr:substr(Body, 1, Index2 - 1), [\n                {FieldName, FieldValue} | OtherHeaders\n            ])\n    end;\nparse_headers(Body, Line, Headers) ->\n    ?LOG_DEBUG(\"line: ~p\", [Line], ?LOGGER_META),\n    case binstr:strchr(Line, $:) of\n        0 ->\n            {lists:reverse(Headers), list_to_binary([Line, \"\\r\\n\", Body])};\n        Index ->\n            FieldName = binstr:substr(Line, 1, Index - 1),\n            F = fun(X) -> X > 32 andalso X < 127 end,\n            case binstr:all(F, FieldName) of\n                true ->\n                    F2 = fun(X) -> (X > 31 andalso X < 127) orelse X == 9 end,\n                    FValue = binstr:strip(binstr:substr(Line, Index + 1)),\n                    FieldValue =\n                        case binstr:all(F2, FValue) of\n                            true ->\n                                FValue;\n                            _ ->\n                                % I couldn't figure out how to use a pure binary comprehension here :(\n                                list_to_binary([filter_non_ascii(C) || <<C:8>> <= FValue])\n                        end,\n                    case binstr:strpos(Body, \"\\r\\n\") of\n                        0 ->\n                            {lists:reverse([{FieldName, FieldValue} | Headers]), Body};\n                        1 ->\n                            {lists:reverse([{FieldName, FieldValue} | Headers]), binstr:substr(Body, 3)};\n                        Index2 ->\n                            parse_headers(binstr:substr(Body, Index2 + 2), binstr:substr(Body, 1, Index2 - 1), [\n                                {FieldName, FieldValue} | Headers\n                            ])\n                    end;\n                false ->\n                    {lists:reverse(Headers), list_to_binary([Line, \"\\r\\n\", Body])}\n            end\n    end.\n\nfilter_non_ascii(C) when (C > 31 andalso C < 127); C == 9 ->\n    <<C>>;\nfilter_non_ascii(_C) ->\n    <<\"?\">>.\n\ndecode_body(Type, Body, _InEncoding, none) ->\n    decode_body(Type, <<<<X/integer>> || <<X>> <= Body, X < 128>>);\ndecode_body(Type, Body, undefined, _OutEncoding) ->\n    decode_body(Type, <<<<X/integer>> || <<X>> <= Body, X < 128>>);\ndecode_body(Type, Body, <<\"x-binaryenc\">>, _OutEncoding) ->\n    % Not IANA and does not represent text, so we pass it through\n    decode_body(Type, Body);\ndecode_body(Type, Body, InEncoding, OutEncoding) ->\n    NewBody = decode_body(Type, Body),\n    InEncodingFixed = fix_encoding(InEncoding),\n    {ok, ConvertedBody} = convert(OutEncoding, InEncodingFixed, NewBody),\n    ConvertedBody.\n\n-spec decode_body(Type :: binary() | 'undefined', Body :: binary()) -> binary().\ndecode_body(undefined, Body) ->\n    Body;\ndecode_body(Type, Body) ->\n    case binstr:to_lower(Type) of\n        <<\"quoted-printable\">> ->\n            decode_quoted_printable(Body);\n        <<\"base64\">> ->\n            decode_base64(Body);\n        _Other ->\n            Body\n    end.\n\ndecode_base64(Body) ->\n    base64:mime_decode(Body).\n\ndecode_quoted_printable(Body) ->\n    decode_quoted_printable(Body, false, <<>>, <<>>).\n\n%% End of Body\ndecode_quoted_printable(<<>>, _HasSoftEOL, _WSPs, Acc) ->\n    Acc;\n%% CRLF after Soft Linebreak\ndecode_quoted_printable(<<$\\r, $\\n, More/binary>>, true, _WSPs, Acc) ->\n    decode_quoted_printable(More, false, <<>>, Acc);\n%% Space or Tab after Soft Linebreak\ndecode_quoted_printable(<<C, More/binary>>, true, _WSPs, Acc) when C =:= $\\s; C =:= $\\t ->\n    decode_quoted_printable(More, true, <<>>, Acc);\n%% Other character after Soft Linebreak\ndecode_quoted_printable(_Body, true, _WSPs, _Acc) ->\n    throw(badchar);\n%% CRLF\ndecode_quoted_printable(<<$\\r, $\\n, More/binary>>, false, _WSPs, Acc) ->\n    decode_quoted_printable(More, false, <<>>, <<Acc/binary, $\\r, $\\n>>);\n%% Space or Tab\ndecode_quoted_printable(<<C, More/binary>>, false, WSPs, Acc) when C =:= $\\s; C =:= $\\t ->\n    decode_quoted_printable(More, false, <<WSPs/binary, C>>, Acc);\n%% Encoded char\ndecode_quoted_printable(<<$=, C1, C2, More/binary>>, false, WSPs, Acc) when\n    C1 >= $0 andalso C1 =< $9 orelse C1 >= $A andalso C1 =< $F orelse C1 >= $a andalso C1 =< $f,\n    C2 >= $0 andalso C2 =< $9 orelse C2 >= $A andalso C2 =< $F orelse C2 >= $a andalso C2 =< $f\n->\n    decode_quoted_printable(More, false, <<>>, <<Acc/binary, WSPs/binary, (unhex(C1)):4, (unhex(C2)):4>>);\n%% Soft Linebreak\ndecode_quoted_printable(<<$=, More/binary>>, false, WSPs, Acc) ->\n    decode_quoted_printable(More, true, <<>>, <<Acc/binary, WSPs/binary>>);\n%% Plain character\ndecode_quoted_printable(<<C, More/binary>>, false, WSPs, Acc) ->\n    decode_quoted_printable(More, false, <<>>, <<Acc/binary, WSPs/binary, C>>).\n\ncheck_headers(Headers) ->\n    Checked = [<<\"MIME-Version\">>, <<\"Date\">>, <<\"From\">>, <<\"Message-ID\">>, <<\"References\">>, <<\"Subject\">>],\n    check_headers(Checked, lists:reverse(Headers)).\n\ncheck_headers([], Headers) ->\n    lists:reverse(Headers);\ncheck_headers([Header | Tail], Headers) ->\n    case get_header_value(Header, Headers) of\n        undefined when Header == <<\"MIME-Version\">> ->\n            check_headers(Tail, [{<<\"MIME-Version\">>, <<\"1.0\">>} | Headers]);\n        undefined when Header == <<\"Date\">> ->\n            check_headers(Tail, [{<<\"Date\">>, list_to_binary(smtp_util:rfc5322_timestamp())} | Headers]);\n        undefined when Header == <<\"From\">> ->\n            erlang:error(missing_from);\n        undefined when Header == <<\"Message-ID\">> ->\n            check_headers(Tail, [{<<\"Message-ID\">>, list_to_binary(smtp_util:generate_message_id())} | Headers]);\n        undefined when Header == <<\"References\">> ->\n            case get_header_value(<<\"In-Reply-To\">>, Headers) of\n                undefined ->\n                    % ok, whatever\n                    check_headers(Tail, Headers);\n                ReplyID ->\n                    check_headers(Tail, [{<<\"References\">>, ReplyID} | Headers])\n            end;\n        References when Header == <<\"References\">> ->\n            % check if the in-reply-to header, if present, is in references\n            case get_header_value(<<\"In-Reply-To\">>, Headers) of\n                undefined ->\n                    % ok, whatever\n                    check_headers(Tail, Headers);\n                ReplyID ->\n                    case binstr:strpos(binstr:to_lower(References), binstr:to_lower(ReplyID)) of\n                        0 ->\n                            % okay, tack on the reply-to to the end of References\n                            check_headers(Tail, [\n                                {<<\"References\">>, list_to_binary([References, \" \", ReplyID])}\n                                | proplists:delete(<<\"References\">>, Headers)\n                            ]);\n                        _Index ->\n                            % nothing to do\n                            check_headers(Tail, Headers)\n                    end\n            end;\n        _ ->\n            check_headers(Tail, Headers)\n    end.\n\nensure_content_headers(Type, SubType, Parameters, Headers, Body, Toplevel) ->\n    CheckHeaders = [<<\"Content-Type\">>, <<\"Content-Disposition\">>, <<\"Content-Transfer-Encoding\">>],\n    CheckHeadersValues = [{Name, get_header_value(Name, Headers)} || Name <- CheckHeaders],\n    ensure_content_headers(CheckHeadersValues, Type, SubType, Parameters, lists:reverse(Headers), Body, Toplevel).\n\nensure_content_headers([], _, _, Parameters, Headers, _, _) ->\n    {Parameters, lists:reverse(Headers)};\nensure_content_headers(\n    [{<<\"Content-Type\">>, undefined} | Tail], Type, SubType, Parameters, Headers, Body, Toplevel\n) when\n    (Type == <<\"text\">> andalso SubType =/= <<\"plain\">>) orelse Type =/= <<\"text\">>\n->\n    %% no content-type header, and its not text/plain\n    CT = io_lib:format(\"~s/~s\", [Type, SubType]),\n    CTP =\n        case Type of\n            <<\"multipart\">> ->\n                Boundary =\n                    case proplists:get_value(<<\"boundary\">>, maps:get(content_type_params, Parameters, [])) of\n                        undefined ->\n                            list_to_binary(smtp_util:generate_message_boundary());\n                        B ->\n                            B\n                    end,\n                [\n                    {<<\"boundary\">>, Boundary}\n                    | proplists:delete(<<\"boundary\">>, maps:get(content_type_params, Parameters, []))\n                ];\n            <<\"text\">> ->\n                Charset =\n                    case proplists:get_value(<<\"charset\">>, maps:get(content_type_params, Parameters, [])) of\n                        undefined ->\n                            guess_charset(Body);\n                        C ->\n                            C\n                    end,\n                [\n                    {<<\"charset\">>, Charset}\n                    | proplists:delete(<<\"charset\">>, maps:get(content_type_params, Parameters, []))\n                ];\n            _ ->\n                maps:get(content_type_params, Parameters, [])\n        end,\n\n    %%CTP = proplists:get_value(<<\"content-type-params\">>, Parameters, [guess_charset(Body)]),\n    CTH = binstr:join([CT | encode_parameters(CTP)], \";\"),\n    NewParameters = Parameters#{content_type_params => CTP},\n    ensure_content_headers(Tail, Type, SubType, NewParameters, [{<<\"Content-Type\">>, CTH} | Headers], Body, Toplevel);\nensure_content_headers(\n    [{<<\"Content-Type\">>, undefined} | Tail],\n    <<\"text\">> = Type,\n    <<\"plain\">> = SubType,\n    Parameters,\n    Headers,\n    Body,\n    Toplevel\n) ->\n    %% no content-type header and its text/plain\n    Charset =\n        case proplists:get_value(<<\"charset\">>, maps:get(content_type_params, Parameters, [])) of\n            undefined ->\n                guess_charset(Body);\n            C ->\n                binstr:to_lower(C)\n        end,\n    case Charset of\n        <<\"us-ascii\">> ->\n            % the default\n            ensure_content_headers(Tail, Type, SubType, Parameters, Headers, Body, Toplevel);\n        _ ->\n            CTP = [\n                {<<\"charset\">>, Charset}\n                | proplists:delete(<<\"charset\">>, maps:get(content_type_params, Parameters, []))\n            ],\n            CTH = binstr:join([<<\"text/plain\">> | encode_parameters(CTP)], \";\"),\n            NewParameters = Parameters#{content_type_params => CTP},\n            ensure_content_headers(\n                Tail, Type, SubType, NewParameters, [{<<\"Content-Type\">>, CTH} | Headers], Body, Toplevel\n            )\n    end;\nensure_content_headers(\n    [{<<\"Content-Transfer-Encoding\">>, undefined} | Tail], Type, SubType, Parameters, Headers, Body, Toplevel\n) when\n    Type =/= <<\"multipart\">>\n->\n    Enc =\n        case maps:get(transfer_encoding, Parameters, undefined) of\n            undefined ->\n                guess_best_encoding(Body);\n            Value ->\n                Value\n        end,\n    case Enc of\n        <<\"7bit\">> ->\n            ensure_content_headers(Tail, Type, SubType, Parameters, Headers, Body, Toplevel);\n        _ ->\n            ensure_content_headers(\n                Tail, Type, SubType, Parameters, [{<<\"Content-Transfer-Encoding\">>, Enc} | Headers], Body, Toplevel\n            )\n    end;\nensure_content_headers(\n    [{<<\"Content-Disposition\">>, undefined} | Tail], Type, SubType, Parameters, Headers, Body, false = Toplevel\n) ->\n    CD = maps:get(disposition, Parameters, <<\"inline\">>),\n    CDP = maps:get(disposition_params, Parameters, []),\n    CDH = binstr:join([CD | encode_parameters(CDP)], \";\"),\n    ensure_content_headers(\n        Tail, Type, SubType, Parameters, [{<<\"Content-Disposition\">>, CDH} | Headers], Body, Toplevel\n    );\nensure_content_headers([_ | Tail], Type, SubType, Parameters, Headers, Body, Toplevel) ->\n    ensure_content_headers(Tail, Type, SubType, Parameters, Headers, Body, Toplevel).\n\nguess_charset(Body) ->\n    case binstr:all(fun(X) -> X < 128 end, Body) of\n        true -> <<\"us-ascii\">>;\n        false -> <<\"utf-8\">>\n    end.\n\nguess_best_encoding(Body) ->\n    case valid_7bit(Body) of\n        true ->\n            <<\"7bit\">>;\n        false ->\n            choose_transformation(Body)\n    end.\n\nchoose_transformation(<<Chunk:200/binary, _, _/binary>>) ->\n    %% Optimization - only analyze 1st 200 bytes\n    choose_transformation(Chunk);\nchoose_transformation(Body) ->\n    {Readable, Encoded} = partition_count_bytes(\n        fun(C) ->\n            C >= 16#20 andalso C =< 16#7E orelse C =:= $\\r orelse C =:= $\\n\n        end,\n        Body\n    ),\n\n    %based on the % of printable characters, choose an encoding\n    if\n        % same as 100 * Readable / (Readable + Encoded) >= 80, but avoiding division\n        Readable >= 4 * Encoded ->\n            %% >80% printable characters\n            <<\"quoted-printable\">>;\n        true ->\n            %% =<80% printable characters\n            <<\"base64\">>\n    end.\n\n%% https://tools.ietf.org/html/rfc2045#section-2.7:\n%% * ASCII codes from 1 to 127\n%% * \\r and \\n are only allowed as `\\r\\n' pair, but not standalone (bare)\n%% * No lines over 998 chars\n%%\n%% Unfortunately, any string that ends with `\\n` matches the regexp, so, we need some pre-checks\nvalid_7bit(<<\"\\n\">>) ->\n    false;\nvalid_7bit(<<\"\\r\">>) ->\n    false;\nvalid_7bit(<<>>) ->\n    true;\nvalid_7bit(<<_>>) ->\n    true;\nvalid_7bit(Body) ->\n    Size = byte_size(Body),\n    case binary:at(Body, Size - 1) =:= $\\n andalso binary:at(Body, Size - 2) =/= $\\r of\n        true ->\n            %% last element is \\n, but the one before the last is not \\r\n            false;\n        false ->\n            %% So: (all except `\\r` and `\\n` in 1-127 range) OR (`\\r\\n`)\n            case re:run(Body, \"^([\\x01-\\x09\\x0b-\\x0c\\x0e-\\x7f]|(\\r\\n))*$\", [{capture, none}]) of\n                match -> not has_lines_over_998(Body);\n                nomatch -> false\n            end\n    end.\n\n%% @doc If `Body' has at least one line (ending with `\\r\\n') that is longer than 998 chars\nhas_lines_over_998(Body) ->\n    Pattern = binary:compile_pattern(<<\"\\r\\n\">>),\n    has_lines_over_998(Body, binary:match(Body, Pattern), 0, Pattern).\n\nhas_lines_over_998(Bin, nomatch, Offset, _) ->\n    %% Last line is over 998?\n    (byte_size(Bin) - Offset) >= 998;\nhas_lines_over_998(_Bin, {FoundAt, 2}, Offset, _Patern) when (FoundAt - Offset) >= 998 ->\n    true;\nhas_lines_over_998(Bin, {FoundAt, 2}, _, Pattern) ->\n    NewOffset = FoundAt + 2,\n    Len = byte_size(Bin) - NewOffset,\n    has_lines_over_998(\n        Bin, binary:match(Bin, Pattern, [{scope, {NewOffset, Len}}]), NewOffset, Pattern\n    ).\n\n-spec encode_parameters([{Name :: binary(), Value :: binary()}]) -> [Parameter :: binary()].\nencode_parameters([[]]) ->\n    [];\nencode_parameters(Parameters) ->\n    lists:foldr(\n        fun({Name, Value}, Acc) ->\n            {Method, EncLen} = decide_param_encoding_method(Value),\n            EncParams = encode_parameter(Method, Name, Value, EncLen),\n            EncParams ++ Acc\n        end,\n        [],\n        Parameters\n    ).\n\n%% Encode a parameter value according to the determined representation\n%% (see decide_param_encoding_method/1).\n%%\n%% If necessary, ie when lines would become longer than 76 characters\n%% (leaving room for the leading continuation WSP and the ending semicolon),\n%% the values are folded following the schema described in RFC2231 section 3.\n-spec encode_parameter(\n    Method :: (plain | quote | encode | encode_utf8), Name :: binary(), Value :: binary(), EncLen :: non_neg_integer()\n) -> [ChunkParameter :: binary()].\nencode_parameter(Method, Name, Value, EncLen) ->\n    encode_parameter(Method, Name, 0, Value, EncLen, []).\n\nencode_parameter(_Method, _Name, _Index, <<>>, _EncLen, Acc) ->\n    lists:reverse(Acc);\nencode_parameter(encode_utf8, Name, 0, Value, EncLen, _Acc) when byte_size(Name) + 9 + EncLen =< 76 ->\n    {Encoded, <<>>} = encode_param_value(encode, Value, 67 - byte_size(Name)),\n    [<<Name/binary, \"*=UTF-8''\", Encoded/binary>>];\nencode_parameter(encode_utf8, Name, 0, Value, EncLen, Acc) ->\n    {Encoded, More} = encode_param_value(encode, Value, 65 - byte_size(Name)),\n    encode_parameter(encode, Name, 1, More, EncLen, [<<Name/binary, \"*0*=UTF-8''\", Encoded/binary>> | Acc]);\nencode_parameter(encode, Name, 0, Value, EncLen, _Acc) when byte_size(Name) + 4 + EncLen =< 76 ->\n    {Encoded, <<>>} = encode_param_value(encode, Value, 72 - byte_size(Name)),\n    [<<Name/binary, \"*=''\", Encoded/binary>>];\nencode_parameter(encode, Name, 0, Value, EncLen, Acc) ->\n    Prefix = <<Name/binary, $*, $0, $*>>,\n    {Encoded, More} = encode_param_value(encode, Value, 73 - byte_size(Prefix)),\n    encode_parameter(encode, Name, 1, More, EncLen, [<<Prefix/binary, \"=''\", Encoded/binary>> | Acc]);\nencode_parameter(encode, Name, Index, Value, EncLen, Acc) ->\n    Prefix = <<Name/binary, $*, (integer_to_binary(Index))/binary, $*>>,\n    {Encoded, More} = encode_param_value(encode, Value, 75 - byte_size(Prefix)),\n    encode_parameter(encode, Name, Index + 1, More, EncLen, [<<Prefix/binary, \"=\", Encoded/binary>> | Acc]);\nencode_parameter(quote, Name, 0, Value, EncLen, _Acc) when byte_size(Name) + 2 + EncLen + 1 =< 76 ->\n    {Quoted, <<>>} = encode_param_value(quote, Value, 73 - byte_size(Name)),\n    [<<Name/binary, $=, $\", Quoted/binary, $\">>];\nencode_parameter(quote, Name, Index, Value, EncLen, Acc) ->\n    Prefix = <<Name/binary, $*, (integer_to_binary(Index))/binary>>,\n    {Quoted, More} = encode_param_value(quote, Value, 73 - byte_size(Prefix)),\n    encode_parameter(quote, Name, Index + 1, More, EncLen, [<<Prefix/binary, $=, $\", Quoted/binary, $\">> | Acc]);\nencode_parameter(plain, Name, 0, Value, EncLen, _Acc) when byte_size(Name) + 1 + EncLen =< 76 ->\n    {Plain, <<>>} = encode_param_value(plain, Value, 75 - byte_size(Name)),\n    [<<Name/binary, $=, Plain/binary>>];\nencode_parameter(plain, Name, Index, Value, EncLen, Acc) ->\n    Prefix = <<Name/binary, $*, (integer_to_binary(Index))/binary>>,\n    {Plain, More} = encode_param_value(plain, Value, 75 - byte_size(Prefix)),\n    encode_parameter(plain, Name, Index + 1, More, EncLen, [<<Prefix/binary, $=, Plain/binary>> | Acc]).\n\n%% Encode a parameter value according to the method\n%% given as the first argument.\n-spec encode_param_value(Method :: (plain | quote | encode), Value :: binary(), Len :: integer()) ->\n    {Chunk :: binary(), Rest :: binary()}.\nencode_param_value(plain, Value, Len) ->\n    %% No encoding necessary, return (part of) the\n    %% value as-is.\n    Len1 = max(Len, 1),\n    case Value of\n        <<Part:Len1/bytes, More/binary>> ->\n            {Part, More};\n        _ ->\n            {Value, <<>>}\n    end;\nencode_param_value(quote, Value, Len) ->\n    %% See encode_param_value_quote/3\n    encode_param_value_quote(Value, Len, <<>>);\nencode_param_value(encode, Value, Len) ->\n    %% See encode_param_value_encode/3\n    encode_param_value_encode(Value, Len, <<>>).\n\n%% Encode (part of) a parameter value by quoting.\n%% \" and \\ are escaped by preceding it with a \\,\n%% everything else remains as-is.\nencode_param_value_quote(<<>>, _Len, Acc) ->\n    {Acc, <<>>};\nencode_param_value_quote(All = <<C, More/binary>>, Len, Acc) ->\n    case C =:= $\" orelse C =:= $\\\\ of\n        true when Len >= 2; Acc =:= <<>> ->\n            encode_param_value_quote(More, Len - 2, <<Acc/binary, $\\\\, C>>);\n        false when Len >= 1; Acc =:= <<>> ->\n            encode_param_value_quote(More, Len - 1, <<Acc/binary, C>>);\n        _ ->\n            {Acc, All}\n    end.\n\n%% Encode (part of) a parameter value according to RFC2231.\n%% Tspecials, CTLs, spaces, *, ', % and the bytes of\n%% multi-byte UTF-8 characters are encoded as a % followed\n%% by the hex representation of the byte values.\n%% Everything else remains as-is.\nencode_param_value_encode(<<>>, _Len, Acc) ->\n    {Acc, <<>>};\nencode_param_value_encode(All = <<C, More/binary>>, Len, Acc) when\n    C =< 16#1F;\n    C =:= 16#7F;\n    C =:= $(;\n    C =:= $);\n    C =:= $<;\n    C =:= $>;\n    C =:= $@;\n    C =:= $,;\n    C =:= $;;\n    C =:= $:;\n    C =:= $/;\n    C =:= $[;\n    C =:= $];\n    C =:= $?;\n    C =:= $=;\n    C =:= $\\s;\n    C =:= $*;\n    C =:= $';\n    C =:= $%\n->\n    case Len >= 3 orelse Acc =:= <<>> of\n        true ->\n            <<N1:4, N2:4>> = <<C>>,\n            encode_param_value_encode(More, Len - 3, <<Acc/binary, $%, (hex(N1)), (hex(N2))>>);\n        false ->\n            {Acc, All}\n    end;\nencode_param_value_encode(All = <<C, More/binary>>, Len, Acc) ->\n    case C >= 16#80 of\n        true when Len >= 3; Acc =:= <<>> ->\n            <<N1:4, N2:4>> = <<C>>,\n            encode_param_value_encode(More, Len - 3, <<Acc/binary, $%, (hex(N1)), (hex(N2))>>);\n        false when Len >= 1; Acc =:= <<>> ->\n            encode_param_value_encode(More, Len - 1, <<Acc/binary, C>>);\n        _ ->\n            {Acc, All}\n    end.\n\n%% Analyze a parameter value and decide how it must be represented based\n%% on the characters contained. At the same time, calculate the number of\n%% bytes the value will take up when encoded for the determined representation.\n%%\n%% plain - value contains no tspecials, CTLs or UTF-8 characters -> representation as-is\n%% quote - value contains tspecials (but no CTLs or UTF-8 characters) -> must be quoted\n%% encode - value contains CTLs -> must be encoded according to RFC2231\n%% encode_utf8 - value contains UTF-8 characters -> must be encoded according to RFC2231\n-spec decide_param_encoding_method(Value :: binary()) ->\n    {Method :: (plain | quote | encode | encode_utf8), EncodedLength :: non_neg_integer()}.\ndecide_param_encoding_method(Value) ->\n    decide_param_encoding_method(Value, plain, 0, 0, 0).\n\ndecide_param_encoding_method(<<>>, Method, LP, LQ, LE) ->\n    L =\n        case Method of\n            plain ->\n                %% LP contains the length for method plain\n                LP;\n            quote ->\n                %% LQ contains the length for method quote\n                LQ;\n            encode ->\n                %% LE contains the length for method encode\n                LE;\n            encode_utf8 ->\n                %% LE contains the length for method encode_utf8\n                LE\n        end,\n    {Method, L};\ndecide_param_encoding_method(<<C/utf8, Rest/binary>>, Method, LP, LQ, LE) when byte_size(<<C/utf8>>) > 1 ->\n    %% multibyte UTF-8 requires encoding and charset; requires 3 bytes\n    decide_param_encoding_method(\n        Rest, change_param_encoding_method(Method, encode_utf8), LP, LQ, LE + 3 * byte_size(<<C/utf8>>)\n    );\ndecide_param_encoding_method(<<C, Rest/binary>>, Method, LP, LQ, LE) when C =< 16#1F; C >= 16#7F ->\n    %% CTLs and upper ASCII requires encoding; requires 3 bytes\n    decide_param_encoding_method(Rest, change_param_encoding_method(Method, encode), LP, LQ, LE + 3);\ndecide_param_encoding_method(<<C, Rest/binary>>, Method, LP, LQ, LE) when C =:= $\"; C =:= $\\\\ ->\n    %% \" and \\ requires quoting; requires 2 bytes when quoting is used, 3 when encoding is used\n    decide_param_encoding_method(Rest, change_param_encoding_method(Method, quote), LP, LQ + 2, LE + 3);\ndecide_param_encoding_method(<<C, Rest/binary>>, Method, LP, LQ, LE) when\n    C =:= $(;\n    C =:= $);\n    C =:= $<;\n    C =:= $>;\n    C =:= $@;\n    C =:= $,;\n    C =:= $;;\n    C =:= $:;\n    C =:= $/;\n    C =:= $[;\n    C =:= $];\n    C =:= $?;\n    C =:= $=;\n    C =:= $\\s\n->\n    %% tspecials require quoting\n    decide_param_encoding_method(Rest, change_param_encoding_method(Method, quote), LP, LQ + 1, LE + 3);\ndecide_param_encoding_method(<<C, Rest/binary>>, Method, LP, LQ, LE) when C =:= $*; C =:= $'; C =:= $% ->\n    %% *, ' and % require 3 bytes when encoding is used, otherwise 1\n    decide_param_encoding_method(Rest, Method, LP + 1, LQ + 1, LE + 3);\ndecide_param_encoding_method(<<_, Rest/binary>>, Method, LP, LQ, LE) ->\n    %% plain characters require 1 byte\n    decide_param_encoding_method(Rest, Method, LP + 1, LQ + 1, LE + 1).\n\n-spec change_param_encoding_method(CurMethod, NewMethod) -> Method when\n    CurMethod :: Method, NewMethod :: Method, Method :: (plain | quote | encode | encode_utf8).\nchange_param_encoding_method(Method, Method) ->\n    %% no change\n    Method;\nchange_param_encoding_method(CurMethod, NewMethod) ->\n    %% between the current and the new encoding method, pick the highest-ranking\n    change_param_encoding_method([encode_utf8, encode, quote], CurMethod, NewMethod).\n\nchange_param_encoding_method([CurMethod | _More], CurMethod, _NewMethod) ->\n    CurMethod;\nchange_param_encoding_method([NewMethod | _More], _CurMethod, NewMethod) ->\n    NewMethod;\nchange_param_encoding_method([_ | More], CurMethod, NewMethod) ->\n    change_param_encoding_method(More, CurMethod, NewMethod);\nchange_param_encoding_method([], _CurMethod, NewMethod) ->\n    NewMethod.\n\nencode_headers([]) ->\n    [];\nencode_headers([{Key, Value} | T] = _Headers) ->\n    EncodedHeader = maybe_encode_folded_header(Key, list_to_binary([Key, \": \", encode_header_value(Key, Value)])),\n    [EncodedHeader | encode_headers(T)].\n\nmaybe_encode_folded_header(H, Hdr) when\n    H =:= <<\"To\">>;\n    H =:= <<\"Cc\">>;\n    H =:= <<\"Bcc\">>;\n    H =:= <<\"Reply-To\">>;\n    H =:= <<\"From\">>\n->\n    Hdr;\nmaybe_encode_folded_header(_H, Hdr) ->\n    encode_folded_header(Hdr, <<>>).\n\nencode_folded_header(Rest, Acc) ->\n    case binstr:split(Rest, <<$;>>, 2) of\n        [_] ->\n            <<Acc/binary, Rest/binary>>;\n        [Before, After] ->\n            NewPart =\n                case After of\n                    <<$\\t, _Rest/binary>> ->\n                        <<Before/binary, \";\\r\\n\">>;\n                    _ ->\n                        <<Before/binary, \";\\r\\n\\t\">>\n                end,\n            encode_folded_header(After, <<Acc/binary, NewPart/binary>>)\n    end.\n\nencode_header_value(H, Value) when\n    H =:= <<\"To\">>;\n    H =:= <<\"Cc\">>;\n    H =:= <<\"Bcc\">>;\n    H =:= <<\"Reply-To\">>;\n    H =:= <<\"From\">>\n->\n    {ok, Addresses} = smtp_util:parse_rfc5322_addresses(Value),\n    {Names, Emails} = lists:unzip(Addresses),\n    NewNames = lists:map(\n        fun\n            (undefined) ->\n                undefined;\n            (Name) ->\n                %% `Name' contains codepoints, but we need bytes\n                rfc2047_utf8_encode(unicode:characters_to_binary(Name))\n        end,\n        Names\n    ),\n    smtp_util:combine_rfc822_addresses(lists:zip(NewNames, Emails));\nencode_header_value(H, Value) when H =:= <<\"Content-Type\">>; H =:= <<\"Content-Disposition\">> ->\n    % Parameters are already encoded.\n    Value;\nencode_header_value(_, Value) ->\n    rfc2047_utf8_encode(Value).\n\nencode_component(_Type, _SubType, _Headers, Params, Body) when is_list(Body) ->\n    % is this a multipart component?\n    Boundary = proplists:get_value(<<\"boundary\">>, maps:get(content_type_params, Params)),\n    % blank line before start of component\n    [<<>>] ++\n        lists:flatmap(\n            fun(Part) ->\n                % start with the boundary\n                [list_to_binary([<<\"--\">>, Boundary])] ++\n                    encode_component_part(Part)\n            end,\n            Body\n            % final boundary (with /--$/)\n        ) ++ [list_to_binary([<<\"--\">>, Boundary, <<\"--\">>])] ++\n        % blank line at the end of the multipart component\n        [<<>>];\nencode_component(_Type, _SubType, Headers, _Params, Body) ->\n    % or an inline component?\n    %encode_component_part({Type, SubType, Headers, Params, Body})\n    encode_body(\n        get_header_value(<<\"Content-Transfer-Encoding\">>, Headers),\n        [Body]\n    ).\n\nencode_component_part({<<\"multipart\">>, SubType, Headers, PartParams, Body}) ->\n    {FixedParams, FixedHeaders} = ensure_content_headers(<<\"multipart\">>, SubType, PartParams, Headers, Body, false),\n    encode_headers(FixedHeaders) ++\n        encode_component(<<\"multipart\">>, SubType, FixedHeaders, FixedParams, Body);\nencode_component_part({Type, SubType, Headers, PartParams, Body}) ->\n    PartData =\n        case Body of\n            {_, _, _, _, _} -> encode_component_part(Body);\n            String -> [String]\n        end,\n    {_FixedParams, FixedHeaders} = ensure_content_headers(Type, SubType, PartParams, Headers, Body, false),\n    encode_headers(FixedHeaders) ++ [<<>>] ++\n        encode_body(\n            get_header_value(<<\"Content-Transfer-Encoding\">>, FixedHeaders),\n            PartData\n        );\nencode_component_part(Part) ->\n    ?LOG_DEBUG(\"encode_component_part couldn't match Part to: ~p\", [Part], ?LOGGER_META),\n    [].\n\nencode_body(undefined, Body) ->\n    Body;\nencode_body(Type, Body) ->\n    case binstr:to_lower(Type) of\n        <<\"quoted-printable\">> ->\n            [InnerBody] = Body,\n            encode_quoted_printable(InnerBody);\n        <<\"base64\">> ->\n            [InnerBody] = Body,\n            wrap_to_76(base64:encode(InnerBody));\n        _ ->\n            Body\n    end.\n\nwrap_to_76(String) ->\n    [wrap_to_76(String, [])].\n\nwrap_to_76(<<>>, Acc) ->\n    list_to_binary(lists:reverse(Acc));\nwrap_to_76(<<Head:76/binary, Tail/binary>>, Acc) ->\n    wrap_to_76(Tail, [<<\"\\r\\n\">>, Head | Acc]);\nwrap_to_76(Head, Acc) ->\n    list_to_binary(lists:reverse([<<\"\\r\\n\">>, Head | Acc])).\n\nencode_quoted_printable(Body) ->\n    [encode_quoted_printable(Body, <<>>, 0, false, <<>>, 0)].\n\n% End of body (this should only happen if the body was empty to begin with)\nencode_quoted_printable(<<>>, Acc, _LineLen, _HasWSP, WordAcc, _WordLen) ->\n    <<Acc/binary, WordAcc/binary>>;\n% CRLF\nencode_quoted_printable(<<$\\r, $\\n, More/binary>>, Acc, _LineLen, _HasWSP, WordAcc, _WordLen) ->\n    encode_quoted_printable(More, <<Acc/binary, WordAcc/binary, $\\r, $\\n>>, 0, false, <<>>, 0);\n% WSP in last position\nencode_quoted_printable(<<C>>, Acc, LineLen, _HasWSP, WordAcc, WordLen) when C =:= $\\s; C =:= $\\t ->\n    Enc = encode_quoted_printable_char(C, true),\n    case LineLen + WordLen + 3 > 76 of\n        true ->\n            % line would become too long -> soft-break before WSP\n            <<Acc/binary, WordAcc/binary, $=, $\\r, $\\n, Enc/binary>>;\n        false ->\n            % character fits on current line\n            <<Acc/binary, WordAcc/binary, Enc/binary>>\n    end;\n% WSP before CRLF\nencode_quoted_printable(<<C, $\\r, $\\n, More/binary>>, Acc, LineLen, _HasWSP, WordAcc, WordLen) when\n    C =:= $\\s; C =:= $\\t\n->\n    Enc = encode_quoted_printable_char(C, true),\n    case LineLen + WordLen + 3 > 76 of\n        true ->\n            % line would become too long -> soft-break before WSP\n            encode_quoted_printable(\n                More, <<Acc/binary, WordAcc/binary, $=, $\\r, $\\n, Enc/binary, $\\r, $\\n>>, 0, false, <<>>, 0\n            );\n        false ->\n            % character fits on current line\n            encode_quoted_printable(More, <<Acc/binary, WordAcc/binary, Enc/binary, $\\r, $\\n>>, 0, false, <<>>, 0)\n    end;\n% Character elsewhere\nencode_quoted_printable(<<C, More/binary>>, Acc, LineLen, HasWSP, WordAcc, WordLen) ->\n    Enc = encode_quoted_printable_char(C, false),\n    EncLen = byte_size(Enc),\n    % mind the 75 here, we need the 76th place for the soft linebreak\n    case LineLen + WordLen + EncLen > 75 of\n        true when C =:= $\\s; C =:= $\\t ->\n            % line would become too long, current char is WSP -> soft-break here (remember we have a WSP)\n            encode_quoted_printable(\n                More, <<Acc/binary, WordAcc/binary, $=, $\\r, $\\n, Enc/binary>>, EncLen, true, <<>>, 0\n            );\n        true when HasWSP, WordLen + EncLen =< 75 ->\n            % line would become too long, we have an earlier WSP and word plus encoded character will fit on a new line -> soft-break at earlier WSP\n            encode_quoted_printable(\n                More, <<Acc/binary, $=, $\\r, $\\n, WordAcc/binary, Enc/binary>>, WordLen + EncLen, false, <<>>, 0\n            );\n        true ->\n            % line would become too long, we have no earlier WSP or word plus encoded character will not fit on a new line -> soft break here\n            encode_quoted_printable(\n                More, <<Acc/binary, WordAcc/binary, $=, $\\r, $\\n, Enc/binary>>, EncLen, false, <<>>, 0\n            );\n        false when C =:= $\\s; C =:= $\\t ->\n            % WSP character fits on line -> move word and WSP to Acc (remember we have a WSP)\n            encode_quoted_printable(\n                More, <<Acc/binary, WordAcc/binary, Enc/binary>>, LineLen + WordLen + EncLen, true, <<>>, 0\n            );\n        false ->\n            % non-WSP character fits on line -> add character to word\n            encode_quoted_printable(More, Acc, LineLen, HasWSP, <<WordAcc/binary, Enc/binary>>, WordLen + EncLen)\n    end.\n\nencode_quoted_printable_char(C, true) ->\n    <<$=, (hex(C div 16#10)), (hex(C rem 16#10))>>;\nencode_quoted_printable_char($\\s, false) ->\n    <<$\\s>>;\nencode_quoted_printable_char($\\t, false) ->\n    <<$\\t>>;\nencode_quoted_printable_char($=, _Force) ->\n    <<$=, $3, $D>>;\nencode_quoted_printable_char(C, _Force) when C =< 16#20; C >= 16#7F ->\n    encode_quoted_printable_char(C, true);\nencode_quoted_printable_char(C, false) ->\n    <<C>>.\n\nget_default_encoding() ->\n    <<\"utf-8//IGNORE\">>.\n\n% convert some common invalid character names into the correct ones\nfix_encoding(Encoding) when Encoding == <<\"utf8\">>; Encoding == <<\"UTF8\">> ->\n    <<\"UTF-8\">>;\nfix_encoding(Encoding) ->\n    Encoding.\n\n% Characters allowed to appear unencoded (RFC 2047 Sections 4.2 and 5):\n%   * lowercase ASCII letters\n%   * uppercase ASCII letters\n%   * decimal digits\n%   * \"!\"\n%   * \"*\"\n%   * \"+\"\n%   * \"-\"\n%   * \"/\"\n% SPACE is not really an allowed letter, but since it encodes to \"_\"\n% and thereby a single byte, we list it as allowed here\n-define(is_rfc2047_q_allowed(C),\n    (C =:= $\\s orelse (C >= $a andalso C =< $z) orelse (C >= $A andalso C =< $Z) orelse\n        (C >= $0 andalso C =< $9) orelse C =:= $! orelse C =:= $* orelse C =:= $+ orelse\n        C =:= $- orelse C =:= $/)\n).\n\n%% @doc Encode a binary or list according to RFC 2047. Input is\n%% assumed to be in UTF-8 encoding bytes; not codepoints.\nrfc2047_utf8_encode(Value) ->\n    rfc2047_utf8_encode(Value, 0, <<\" \">>).\n\nrfc2047_utf8_encode(Value, PrefixLen, LineIndent) when is_binary(Value) ->\n    case is_ascii_printable(Value) of\n        true ->\n            % don't encode if all characters are printable ASCII\n            Value;\n        false ->\n            {Readable, Encoded} = partition_count_bytes(fun(C) -> ?is_rfc2047_q_allowed(C) end, Value),\n            Enc =\n                if\n                    Readable >= Encoded ->\n                        % most characters would be readable in Q-Encoding,\n                        % so we use it\n                        q;\n                    true ->\n                        % most characters would have to be encoded in Q-Encoding,\n                        % so we use B-Encoding instead\n                        b\n                end,\n            rfc2047_utf8_encode(Enc, Value, <<>>, PrefixLen, LineIndent)\n    end;\nrfc2047_utf8_encode(Value, PrefixLen, LineIndent) ->\n    rfc2047_utf8_encode(list_to_binary(Value), PrefixLen, LineIndent).\n\nrfc2047_utf8_encode(_Enc, <<>>, Acc, _PrefixLen, _LineIndent) ->\n    Acc;\nrfc2047_utf8_encode(b, More, Acc, PrefixLen, LineIndent) ->\n    % B-Encoding\n    % An encoded word must not be longer than 75 bytes,\n    % including the leading \"=?\", charset name, \"?B?\" and\n    % the trailing \"?=\". Since the charset name is fixed to\n    % \"UTF-8\", 63 remain for encoded text. Using Base64,\n    % a maximum of 45 raw bytes can be encoded in 63 bytes.\n    rfc2047_utf8_encode(b, More, Acc, <<>>, byte_size(LineIndent), LineIndent, 46 - PrefixLen);\nrfc2047_utf8_encode(q, More, Acc, PrefixLen, LineIndent) ->\n    % Q-Encoding\n    % An encoded word must not be longer than 75 bytes,\n    % including the leading \"=?\", charset name, \"=?UTF-8?Q?\" and\n    % the trailing \"?=\". Since the charset name is fixed to\n    % \"UTF-8\", 63 remain for encoded text. Using Quoted-Printable,\n    % between 21 and 63 raw bytes can be encoded in 63 bytes.\n    rfc2047_utf8_encode(q, More, Acc, <<>>, byte_size(LineIndent), LineIndent, 63 - PrefixLen).\n\nrfc2047_utf8_encode(Enc, <<>>, Acc, WordAcc, _PrefixLen, LineIndent, _Left) ->\n    rfc2047_append_word(Acc, WordAcc, Enc, LineIndent);\nrfc2047_utf8_encode(Enc, All = <<C/utf8, More/binary>>, Acc, WordAcc, PrefixLen, LineIndent, Left) ->\n    % convert codepoint back to UTF-8 encoded bytes\n    Bytes = <<C/utf8>>,\n    Size = byte_size(Bytes),\n    Reqd =\n        case Enc of\n            q when not ?is_rfc2047_q_allowed(C) ->\n                3 * Size;\n            q ->\n                Size;\n            b ->\n                Size\n        end,\n    case Left >= Reqd of\n        true ->\n            rfc2047_utf8_encode(Enc, More, Acc, <<WordAcc/binary, Bytes/binary>>, PrefixLen, LineIndent, Left - Reqd);\n        false ->\n            rfc2047_utf8_encode(Enc, All, rfc2047_append_word(Acc, WordAcc, Enc, LineIndent), PrefixLen, LineIndent)\n    end.\n\nrfc2047_append_word(Acc, <<>>, _Enc, _LineIndent) ->\n    % empty word\n    Acc;\nrfc2047_append_word(<<>>, Word, Enc, _LineIndent) ->\n    % first word in Acc\n    rfc2047_encode_word(Word, Enc);\nrfc2047_append_word(Acc, Word, Enc, LineIndent) ->\n    % subsequent word in Acc\n    <<Acc/binary, $\\r, $\\n, LineIndent/binary, (rfc2047_encode_word(Word, Enc))/binary>>.\n\nrfc2047_encode_word(Word, q) ->\n    <<\"=?UTF-8?Q?\", (rfc2047_q_encode(Word))/binary, \"?=\">>;\nrfc2047_encode_word(Word, b) ->\n    <<\"=?UTF-8?B?\", (base64:encode(Word))/binary, \"?=\">>.\n\nrfc2047_q_encode(<<>>) ->\n    <<>>;\nrfc2047_q_encode(<<$\\s, More/binary>>) ->\n    % SPACE -> _\n    <<$_, (rfc2047_q_encode(More))/binary>>;\nrfc2047_q_encode(<<C, More/binary>>) when ?is_rfc2047_q_allowed(C) ->\n    % character which needs no encoding\n    <<C, (rfc2047_q_encode(More))/binary>>;\nrfc2047_q_encode(<<N1:4, N2:4, More/binary>>) ->\n    % characters which need encoding -> =XY\n    <<$=, (hex(N1)), (hex(N2)), (rfc2047_q_encode(More))/binary>>.\n\nis_ascii_printable(<<>>) ->\n    'true';\nis_ascii_printable(<<H, T/binary>>) when H >= 32 andalso H =< 126 ->\n    is_ascii_printable(T);\nis_ascii_printable(_) ->\n    'false'.\n\nhex(N) when N >= 10 -> N + $A - 10;\nhex(N) -> N + $0.\n\nunhex(C) when C >= $a -> C - $a + 10;\nunhex(C) when C >= $A -> C - $A + 10;\nunhex(C) -> C - $0.\n\npartition_count_bytes(Fun, Bin) ->\n    partition_count_bytes(Fun, Bin, {0, 0}).\n\npartition_count_bytes(_Fun, <<>>, PartitionCounts) ->\n    PartitionCounts;\npartition_count_bytes(Fun, <<C, More/binary>>, {Trues, Falses}) ->\n    NewPartitionCounts =\n        case Fun(C) of\n            true -> {Trues + 1, Falses};\n            false -> {Trues, Falses + 1}\n        end,\n    partition_count_bytes(Fun, More, NewPartitionCounts).\n\n%% @doc DKIM sign an email\n%% DKIM sign functions\n%% RFC 6376\n%% `h' - list of headers to sign (lowercased binary)\n%% `c' - {Headers, Body} canonicalization type. Only {simple, simple} and\n%% {relaxed, simple} supported for now.\n%% be located in \"foo.bar._domainkey.example.com\" (see RFC-6376 #3.6.2.1).\n%% `t' - signature timestamp: 'now' or UTC {Date, Time}\n%% `x' - signature expiration time: UTC {Date, Time}\n%% `a` - signing algorithm (default: `rsa-sha256`):\n%% `private_key' - private key, to sign emails. May be of 2 types: encrypted and\n%% plain in PEM format:\n%% RSA\n%% `{pem_plain, KeyBinary}' - generated by <code>openssl genrsa -out out-file.pem 1024</code>\n%% `{pem_encrypted, KeyBinary, Password}' - generated by, eg\n%%  <code>openssl genrsa -des3 -out out-file.pem 1024</code>\n%% RFC8463\n%% Ed25519 - Erlang/OTP 24.1+ only!\n%% `{pem_plain, KeyBinary}' - generated by <code>openssl genpkey -algorithm ed25519 -out out-file.pem</code>\n%% `{pem_encrypted, KeyBinary, Password}' - generated by, eg\n%%  <code>openssl genpkey -des3 -algorithm ed25519 -out out-file.pem</code>\n%%  3rd paramerter is password to decrypt the key.\n-spec dkim_sign_email([binary()], binary(), dkim_options()) -> [binary()].\ndkim_sign_email(Headers, Body, Opts) ->\n    HeadersToSign = proplists:get_value(h, Opts, [<<\"from\">>, <<\"to\">>, <<\"subject\">>, <<\"date\">>]),\n    SDID = proplists:get_value(d, Opts),\n    Selector = proplists:get_value(s, Opts),\n    %% BodyLength = proplists:get_value(l, Opts),\n    OptionalTags = lists:foldl(\n        fun(Key, Acc) ->\n            case proplists:get_value(Key, Opts) of\n                undefined -> Acc;\n                Value -> [{Key, Value} | Acc]\n            end\n        end,\n        [],\n        [t, x]\n    ),\n    {HdrsCanT, BodyCanT} = Can = proplists:get_value(c, Opts, {relaxed, simple}),\n    Algorithm = proplists:get_value(a, Opts, 'rsa-sha256'),\n    PrivateKey = proplists:get_value(private_key, Opts),\n\n    %% hash body\n    CanBody = dkim_canonicalize_body(Body, BodyCanT),\n    BodyHash = dkim_hash_body(CanBody),\n    %% {b, <<>>},\n    Tags = [\n        {v, 1},\n        {a, Algorithm},\n        {bh, BodyHash},\n        {c, Can},\n        {d, SDID},\n        {h, HeadersToSign},\n        {s, Selector}\n        | OptionalTags\n    ],\n    %% hash headers\n    Headers1 = dkim_filter_headers(Headers, HeadersToSign),\n    CanHeaders = dkim_canonicalize_headers(Headers1, HdrsCanT),\n    [DkimHeaderNoB] = dkim_canonicalize_headers([dkim_make_header([{b, undefined} | Tags])], HdrsCanT),\n    DataHash = dkim_hash_data(CanHeaders, DkimHeaderNoB),\n    %% sign\n    Signature = dkim_sign(DataHash, Algorithm, PrivateKey),\n    DkimHeader = dkim_make_header([{b, Signature} | Tags]),\n    [DkimHeader | Headers].\n\ndkim_filter_headers(Headers, HeadersToSign) ->\n    KeyedHeaders = [\n        begin\n            [Name, _] = binary:split(Hdr, <<\":\">>),\n            {binstr:strip(binstr:to_lower(Name)), Hdr}\n        end\n     || Hdr <- Headers\n    ],\n    WithUndef = [get_header_value(binstr:to_lower(Name), KeyedHeaders) || Name <- HeadersToSign],\n    [Hdr || Hdr <- WithUndef, Hdr =/= undefined].\n\ndkim_canonicalize_headers(Headers, simple) ->\n    Headers;\ndkim_canonicalize_headers(Headers, relaxed) ->\n    dkim_canonic_hdrs_relaxed(Headers).\n\ndkim_canonic_hdrs_relaxed([Hdr | Rest]) ->\n    [Name, Value] = binary:split(Hdr, <<\":\">>),\n    LowStripName = binstr:to_lower(binstr:strip(Name)),\n\n    UnfoldedHdrValue = binary:replace(Value, <<\"\\r\\n\">>, <<>>, [global]),\n    SingleWSValue = re:replace(UnfoldedHdrValue, \"[\\t ]+\", \" \", [global, {return, binary}]),\n    StrippedWithName = <<LowStripName/binary, \":\", (binstr:strip(SingleWSValue))/binary>>,\n    [StrippedWithName | dkim_canonic_hdrs_relaxed(Rest)];\ndkim_canonic_hdrs_relaxed([]) ->\n    [].\n\ndkim_canonicalize_body(<<>>, simple) ->\n    <<\"\\r\\n\">>;\ndkim_canonicalize_body(Body, simple) ->\n    re:replace(Body, \"(\\r\\n)*$\", \"\\r\\n\", [{return, binary}]);\ndkim_canonicalize_body(_Body, relaxed) ->\n    throw({not_supported, dkim_body_relaxed}).\n\ndkim_hash_body(CanonicBody) ->\n    crypto:hash(sha256, CanonicBody).\n%% crypto:sha256(CanonicBody).\n\n%% RFC 5.5 & 3.7\ndkim_hash_data(CanonicHeaders, DkimHeader) ->\n    JoinedHeaders = <<<<Hdr/binary, \"\\r\\n\">> || Hdr <- CanonicHeaders>>,\n    crypto:hash(sha256, <<JoinedHeaders/binary, DkimHeader/binary>>).\n\n%% TODO: Remove once we require Erlang/OTP 24.1+\n%% Related Erlang/OTP bug: https://github.com/erlang/otp/pull/5157\ned25519_supported() ->\n    {ok, PublicKeyAppVersionString} = application:get_key(public_key, vsn),\n    PublicKeyAppVersionList =\n        lists:map(fun erlang:list_to_integer/1, string:tokens(PublicKeyAppVersionString, \".\")),\n    PublicKeyAppVersionList >= [1, 11, 2].\n\ndkim_get_algorithm_digest(Algorithm) ->\n    case Algorithm of\n        'rsa-sha256' ->\n            sha256;\n        'ed25519-sha256' ->\n            case ed25519_supported() of\n                true ->\n                    none;\n                false ->\n                    throw(\"DKIM with Ed25519 requires Erlang/OTP 24.1+\")\n            end\n    end.\n\ndkim_sign(DataHash, Algorithm, {pem_plain, PrivBin}) ->\n    [PrivEntry] = public_key:pem_decode(PrivBin),\n    Digest = dkim_get_algorithm_digest(Algorithm),\n    Key = public_key:pem_entry_decode(PrivEntry),\n    public_key:sign({digest, DataHash}, Digest, Key);\ndkim_sign(DataHash, Algorithm, {pem_encrypted, EncPrivBin, Passwd}) ->\n    [EncPrivEntry] = public_key:pem_decode(EncPrivBin),\n    Digest = dkim_get_algorithm_digest(Algorithm),\n    Key = public_key:pem_entry_decode(EncPrivEntry, Passwd),\n    public_key:sign({digest, DataHash}, Digest, Key).\n\ndkim_make_header(Tags) ->\n    %so {b, ...} became last tag\n    RevTags = lists:reverse(Tags),\n    EncodedTags = binstr:join([dkim_encode_tag(K, V) || {K, V} <- RevTags], <<\"; \">>),\n    binstr:join(encode_headers([{<<\"DKIM-Signature\">>, EncodedTags}]), <<\"\\r\\n\">>).\n\n%% RFC #3.5\ndkim_encode_tag(v, 1) ->\n    %% version\n    <<\"v=1\">>;\ndkim_encode_tag(a, Algorithm) ->\n    %% algorithm\n    <<\"a=\", (atom_to_binary(Algorithm, utf8))/binary>>;\ndkim_encode_tag(b, undefined) ->\n    %% signature (when hashing with no digest)\n    <<\"b=\">>;\ndkim_encode_tag(b, V) ->\n    %% signature\n    B64Sign = base64:encode(V),\n    <<\"b=\", B64Sign/binary>>;\ndkim_encode_tag(bh, V) ->\n    %% body hash\n    B64Sign = base64:encode(V),\n    <<\"bh=\", B64Sign/binary>>;\n% 'relaxed' for body not supported yet\ndkim_encode_tag(c, {Hdrs, simple}) ->\n    %% canonicalization type\n    <<\"c=\", (atom_to_binary(Hdrs, utf8))/binary, \"/simple\">>;\ndkim_encode_tag(d, Domain) ->\n    %% SDID (domain)\n    <<\"d=\", Domain/binary>>;\ndkim_encode_tag(h, Hdrs) ->\n    %% headers fields (case-insensitive, \":\" separated)\n    Joined = binstr:join([binstr:to_lower(H) || H <- Hdrs], <<\":\">>),\n    <<\"h=\", Joined/binary>>;\ndkim_encode_tag(i, V) ->\n    %% AUID\n    QPValue = dkim_qp_tag_value(V),\n    <<\"i=\", QPValue/binary>>;\ndkim_encode_tag(l, IntVal) ->\n    %% body length count\n    BinVal = list_to_binary(integer_to_list(IntVal)),\n    <<\"l=\", (BinVal)/binary>>;\ndkim_encode_tag(q, [<<\"dns/txt\">>]) ->\n    %% query methods (':' separated)\n    <<\"q=dns/txt\">>;\ndkim_encode_tag(s, Selector) ->\n    %% selector\n    <<\"s=\", Selector/binary>>;\ndkim_encode_tag(t, now) ->\n    dkim_encode_tag(t, calendar:universal_time());\ndkim_encode_tag(t, DateTime) ->\n    %% timestamp\n    BinTs = datetime_to_bin_timestamp(DateTime),\n    <<\"t=\", BinTs/binary>>;\ndkim_encode_tag(x, DateTime) ->\n    %% signature expiration\n    BinTs = datetime_to_bin_timestamp(DateTime),\n    <<\"x=\", BinTs/binary>>;\n%% dkim_encode_tag(z, Hdrs) ->\n%%\t   %% copied header fields\n%%\t   Joined = dkim_qp_tag_value(binstr:join([(H) || H <- Hdrs], <<\"|\">>)),\n%%\t   <<\"z=\", Joined/binary>>;\ndkim_encode_tag(K, V) when is_binary(K), is_binary(V) ->\n    <<K/binary, V/binary>>.\n\ndkim_qp_tag_value(Value) ->\n    %% XXX: this not fully satisfy #2.11\n    [QPValue] = encode_quoted_printable(Value),\n    binary:replace(QPValue, <<\";\">>, <<\"=3B\">>).\n\ndatetime_to_bin_timestamp(DateTime) ->\n    % calendar:datetime_to_gregorian_seconds({{1970,1,1}, {0,0,0}})\n    EpochStart = 62167219200,\n    UnixTimestamp = calendar:datetime_to_gregorian_seconds(DateTime) - EpochStart,\n    list_to_binary(integer_to_list(UnixTimestamp)).\n\n%% /DKIM\n\n-ifdef(TEST).\n\nparse_with_comments_test_() ->\n    [\n        {\"bleh\", fun() ->\n            ?assertEqual(<<\"1.0\">>, parse_with_comments(<<\"1.0\">>)),\n            ?assertEqual(<<\"1.0\">>, parse_with_comments(<<\"1.0  (produced by MetaSend Vx.x)\">>)),\n            ?assertEqual(<<\"1.0\">>, parse_with_comments(<<\"(produced by MetaSend Vx.x) 1.0\">>)),\n            ?assertEqual(<<\"1.0\">>, parse_with_comments(<<\"1.(produced by MetaSend Vx.x)0\">>))\n        end},\n        {\"comments that parse as empty\", fun() ->\n            ?assertEqual(<<>>, parse_with_comments(<<\"(comment (nested (deeply)) (and (oh no!) again))\">>)),\n            ?assertEqual(<<>>, parse_with_comments(<<\"(\\\\)\\\\\\\\)\">>)),\n            ?assertEqual(<<>>, parse_with_comments(<<\"(by way of Whatever <redir@my.org>)    (generated by Eudora)\">>))\n        end},\n        {\"some more\", fun() ->\n            ?assertEqual(\n                <<\":sysmail@  group. org, Muhammed. Ali @Vegas.WBA\">>,\n                parse_with_comments(<<\"\\\":sysmail\\\"@  group. org, Muhammed.(the greatest) Ali @(the)Vegas.WBA\">>)\n            ),\n            ?assertEqual(\n                <<\"Pete <pete@silly.test>\">>,\n                parse_with_comments(<<\"Pete(A wonderful \\\\) chap) <pete(his account)@silly.test(his host)>\">>)\n            )\n        end},\n        {\"non list values\", fun() ->\n            ?assertEqual(undefined, parse_with_comments(undefined)),\n            ?assertEqual(17, parse_with_comments(17))\n        end},\n        {\"Parens within quotes ignored\", fun() ->\n            ?assertEqual(<<\"Height (from xkcd).eml\">>, parse_with_comments(<<\"\\\"Height (from xkcd).eml\\\"\">>)),\n            ?assertEqual(<<\"Height (from xkcd).eml\">>, parse_with_comments(<<\"\\\"Height \\(from xkcd\\).eml\\\"\">>))\n        end},\n        {\"Escaped quotes are handled correctly\", fun() ->\n            ?assertEqual(<<\"Hello \\\"world\\\"\">>, parse_with_comments(<<\"Hello \\\\\\\"world\\\\\\\"\">>)),\n            ?assertEqual(\n                <<\"<boss@nil.test>, Giant; \\\"Big\\\" Box <sysservices@example.net>\">>,\n                parse_with_comments(<<\"<boss@nil.test>, \\\"Giant; \\\\\\\"Big\\\\\\\" Box\\\" <sysservices@example.net>\">>)\n            )\n        end},\n        {\"backslash not part of a quoted pair\", fun() ->\n            ?assertEqual(<<\"AC \\\\ DC\">>, parse_with_comments(<<\"AC \\\\ DC\">>)),\n            ?assertEqual(<<\"AC  DC\">>, parse_with_comments(<<\"AC ( \\\\ ) DC\">>))\n        end},\n        {\"Unterminated quotes or comments\", fun() ->\n            ?assertError(unterminated_quotes, parse_with_comments(<<\"\\\"Hello there \">>)),\n            ?assertError(unterminated_quotes, parse_with_comments(<<\"\\\"Hello there \\\\\\\"\">>)),\n            ?assertError(unterminated_comment, parse_with_comments(<<\"(Hello there \">>)),\n            ?assertError(unterminated_comment, parse_with_comments(<<\"(Hello there \\\\\\)\">>))\n        end}\n    ].\n\nparse_content_type_test_() ->\n    [\n        {\"parsing content types\", fun() ->\n            ?assertEqual(\n                {<<\"text\">>, <<\"plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}]},\n                parse_content_type(<<\"text/plain; charset=us-ascii (Plain text)\">>)\n            ),\n            ?assertEqual(\n                {<<\"text\">>, <<\"plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}]},\n                parse_content_type(<<\"text/plain; charset=\\\"us-ascii\\\"\">>)\n            ),\n            ?assertEqual(\n                {<<\"text\">>, <<\"plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}]},\n                parse_content_type(<<\"Text/Plain; Charset=\\\"us-ascii\\\"\">>)\n            ),\n            ?assertEqual(\n                {<<\"multipart\">>, <<\"mixed\">>, [{<<\"boundary\">>, <<\"----_=_NextPart_001_01C9DCAE.1F2CB390\">>}]},\n                parse_content_type(<<\"multipart/mixed; boundary=\\\"----_=_NextPart_001_01C9DCAE.1F2CB390\\\"\">>)\n            )\n        end},\n        {\"parsing content type with a tab in it\", fun() ->\n            ?assertEqual(\n                {<<\"text\">>, <<\"plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}]},\n                parse_content_type(<<\"text/plain;\\tcharset=us-ascii\">>)\n            ),\n            ?assertEqual(\n                {<<\"text\">>, <<\"plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}, {<<\"foo\">>, <<\"bar\">>}]},\n                parse_content_type(<<\"text/plain;\\tcharset=us-ascii;\\tfoo=bar\">>)\n            )\n        end},\n        {\"invalid content types\", fun() ->\n            ?assertThrow(bad_content_type, parse_content_type(<<\"text\\\\plain; charset=us-ascii\">>)),\n            ?assertThrow(bad_content_type, parse_content_type(<<\"text/plain; charset us-ascii\">>))\n        end}\n    ].\n\nparse_content_disposition_test_() ->\n    [\n        {\"parsing valid dispositions\", fun() ->\n            ?assertEqual({<<\"inline\">>, []}, parse_content_disposition(<<\"inline\">>)),\n            ?assertEqual({<<\"inline\">>, []}, parse_content_disposition(<<\"inline;\">>)),\n            ?assertEqual(\n                {<<\"attachment\">>, [\n                    {<<\"filename\">>, <<\"genome.jpeg\">>},\n                    {<<\"modification-date\">>, <<\"Wed, 12 Feb 1997 16:29:51 -0500\">>}\n                ]},\n                parse_content_disposition(\n                    <<\"attachment; filename=genome.jpeg;modification-date=\\\"Wed, 12 Feb 1997 16:29:51 -0500\\\";\">>\n                )\n            ),\n            ?assertEqual(\n                {<<\"text/plain\">>, [{<<\"charset\">>, <<\"us-ascii\">>}]},\n                parse_content_disposition(<<\"text/plain; charset=us-ascii (Plain text)\">>)\n            )\n        end},\n        {\"invalid dispositions\", fun() ->\n            ?assertThrow(bad_disposition, parse_content_disposition(<<\"inline; =bar\">>)),\n            ?assertThrow(bad_disposition, parse_content_disposition(<<\"inline; bar\">>))\n        end}\n    ].\n\nvarious_parsing_test_() ->\n    [\n        {\"split_body_by_boundary test\", fun() ->\n            ?assertEqual(\n                [{[], <<\"foo bar baz\">>}], split_body_by_boundary_(<<\"stuff\\r\\nfoo bar baz\">>, <<\"--bleh\">>, [], [])\n            ),\n            ?assertEqual(\n                [{[], <<\"foo\\r\\n\">>}, {[], <<>>}, {[], <<>>}, {[], <<\"bar baz\">>}],\n                split_body_by_boundary_(\n                    <<\"stuff\\r\\nfoo\\r\\n--bleh\\r\\n--bleh\\r\\n--bleh-- stuff\\r\\nbar baz\">>, <<\"--bleh\">>, [], []\n                )\n            ),\n            %?assertEqual([{[], []}, {[], []}, {[], \"bar baz\"}], split_body_by_boundary_(\"\\r\\n--bleh\\r\\n--bleh\\r\\n\", \"--bleh\", [], [])),\n            %?assertMatch([{\"text\", \"plain\", [], _,\"foo\\r\\n\"}], split_body_by_boundary(\"stuff\\r\\nfoo\\r\\n--bleh\\r\\n--bleh\\r\\n--bleh-- stuff\\r\\nbar baz\", \"--bleh\", \"1.0\", []))\n            ?assertEqual({[], <<\"foo: bar\\r\\n\">>}, parse_headers(<<\"\\r\\nfoo: bar\\r\\n\">>)),\n            ?assertEqual({[{<<\"foo\">>, <<\"barbaz\">>}], <<>>}, parse_headers(<<\"foo: bar\\r\\n baz\\r\\n\">>)),\n            ?assertEqual({[], <<\" foo bar baz\\r\\nbam\">>}, parse_headers(<<\"\\sfoo bar baz\\r\\nbam\">>)),\n            ok\n        end},\n        {\"Headers with non-ASCII characters\", fun() ->\n            ?assertEqual({[{<<\"foo\">>, <<\"bar ?? baz\">>}], <<>>}, parse_headers(<<\"foo: bar ø baz\\r\\n\"/utf8>>)),\n            ?assertEqual({[], <<\"bär: bar baz\\r\\n\"/utf8>>}, parse_headers(<<\"bär: bar baz\\r\\n\"/utf8>>))\n        end},\n        {\"Headers with tab characters\", fun() ->\n            ?assertEqual({[{<<\"foo\">>, <<\"bar\t\tbaz\">>}], <<>>}, parse_headers(<<\"foo: bar\t\tbaz\\r\\n\">>))\n        end}\n    ].\n\n-define(IMAGE_MD5, <<110, 130, 37, 247, 39, 149, 224, 61, 114, 198, 227, 138, 113, 4, 198, 60>>).\n\nparse_example_mails_test_() ->\n    Getmail = fun(File) ->\n        {ok, Email} = file:read_file(string:concat(\"test/fixtures/\", File)),\n        %Email = binary_to_list(Bin),\n        decode(Email)\n    end,\n    [\n        {\"parse a plain text email\", fun() ->\n            Decoded = Getmail(\"Plain-text-only.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"text\">>, <<\"plain\">>}, {Type, SubType}),\n            ?assertEqual(<<\"This message contains only plain text.\\r\\n\">>, Body)\n        end},\n        {\"parse a Python smtplib plain text email\", fun() ->\n            Decoded = Getmail(\"python-smtp-lib.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"text\">>, <<\"plain\">>}, {Type, SubType}),\n            ?assertEqual(<<\"Hello world Python.\\r\\n\">>, Body)\n        end},\n        {\"parse a plain text email with no content type\", fun() ->\n            Decoded = Getmail(\"Plain-text-only-no-content-type.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"text\">>, <<\"plain\">>}, {Type, SubType}),\n            ?assertEqual(<<\"This message contains only plain text.\\r\\n\">>, Body)\n        end},\n        {\"parse a plain text email with no MIME header\", fun() ->\n            {Type, SubType, _Headers, _Properties, Body} =\n                Getmail(\"Plain-text-only-no-MIME.eml\"),\n            ?assertEqual({<<\"text\">>, <<\"plain\">>}, {Type, SubType}),\n            ?assertEqual(<<\"This message contains only plain text.\\r\\n\">>, Body)\n        end},\n        {\"parse an email that says it is multipart but contains no boundaries\", fun() ->\n            ?assertError(missing_boundary, Getmail(\"Plain-text-only-with-boundary-header.eml\"))\n        end},\n        {\"parse a multipart email with no MIME header\", fun() ->\n            % We now insert a default Mime for missing Mime headers\n            % ?assertError(non_mime_multipart, Getmail(\"rich-text-no-MIME.eml\"))\n            ?assertMatch(\n                {<<\"multipart\">>, <<\"alternative\">>, _, _, [\n                    {<<\"text\">>, <<\"plain\">>, _, _, _}, {<<\"text\">>, <<\"html\">>, _, _, _}\n                ]},\n                Getmail(\"rich-text-no-MIME.eml\")\n            )\n        end},\n        {\"rich text\", fun() ->\n            %% pardon my naming here.  apparently 'rich text' in mac mail\n            %% means 'html'.\n            Decoded = Getmail(\"rich-text.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"multipart\">>, <<\"alternative\">>}, {Type, SubType}),\n            ?assertEqual(2, length(Body)),\n            [Plain, Html] = Body,\n            ?assertEqual({5, 5}, {tuple_size(Plain), tuple_size(Html)}),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, <<\"This message contains rich text.\">>}, Plain),\n            ?assertMatch(\n                {<<\"text\">>, <<\"html\">>, _, _,\n                    <<\"<html><body style=\\\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \\\"><b>This </b><i>message </i><span class=\\\"Apple-style-span\\\" style=\\\"text-decoration: underline;\\\">contains </span>rich text.</body></html>\">>},\n                Html\n            )\n        end},\n        {\"rich text no boundary\", fun() ->\n            ?assertError(no_boundary, Getmail(\"rich-text-no-boundary.eml\"))\n        end},\n        {\"rich text missing first boundary\", fun() ->\n            % TODO - should we handle this more elegantly?\n            Decoded = Getmail(\"rich-text-missing-first-boundary.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"multipart\">>, <<\"alternative\">>}, {Type, SubType}),\n            ?assertEqual(1, length(Body)),\n            [Html] = Body,\n            ?assertEqual(5, tuple_size(Html)),\n            ?assertMatch(\n                {<<\"text\">>, <<\"html\">>, _, _,\n                    <<\"<html><body style=\\\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \\\"><b>This </b><i>message </i><span class=\\\"Apple-style-span\\\" style=\\\"text-decoration: underline;\\\">contains </span>rich text.</body></html>\">>},\n                Html\n            )\n        end},\n        {\"rich text missing last boundary\", fun() ->\n            ?assertError(missing_last_boundary, Getmail(\"rich-text-missing-last-boundary.eml\"))\n        end},\n        {\"rich text wrong last boundary\", fun() ->\n            ?assertError(missing_last_boundary, Getmail(\"rich-text-broken-last-boundary.eml\"))\n        end},\n        {\"rich text missing text content type\", fun() ->\n            %% pardon my naming here.  apparently 'rich text' in mac mail\n            %% means 'html'.\n            Decoded = Getmail(\"rich-text-no-text-contenttype.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"multipart\">>, <<\"alternative\">>}, {Type, SubType}),\n            ?assertEqual(2, length(Body)),\n            [Plain, Html] = Body,\n            ?assertEqual({5, 5}, {tuple_size(Plain), tuple_size(Html)}),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, <<\"This message contains rich text.\">>}, Plain),\n            ?assertMatch(\n                {<<\"text\">>, <<\"html\">>, _, _,\n                    <<\"<html><body style=\\\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \\\"><b>This </b><i>message </i><span class=\\\"Apple-style-span\\\" style=\\\"text-decoration: underline;\\\">contains </span>rich text.</body></html>\">>},\n                Html\n            )\n        end},\n        {\"text attachment only\", fun() ->\n            Decoded = Getmail(\"text-attachment-only.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"multipart\">>, <<\"mixed\">>}, {Type, SubType}),\n            ?assertEqual(1, length(Body)),\n            Rich =\n                <<\"{\\\\rtf1\\\\ansi\\\\ansicpg1252\\\\cocoartf949\\\\cocoasubrtf460\\r\\n{\\\\fonttbl\\\\f0\\\\fswiss\\\\fcharset0 Helvetica;}\\r\\n{\\\\colortbl;\\\\red255\\\\green255\\\\blue255;}\\r\\n\\\\margl1440\\\\margr1440\\\\vieww9000\\\\viewh8400\\\\viewkind0\\r\\n\\\\pard\\\\tx720\\\\tx1440\\\\tx2160\\\\tx2880\\\\tx3600\\\\tx4320\\\\tx5040\\\\tx5760\\\\tx6480\\\\tx7200\\\\tx7920\\\\tx8640\\\\ql\\\\qnatural\\\\pardirnatural\\r\\n\\r\\n\\\\f0\\\\fs24 \\\\cf0 This is a basic rtf file.}\">>,\n            ?assertMatch([{<<\"text\">>, <<\"rtf\">>, _, _, Rich}], Body)\n        end},\n        {\"image attachment only\", fun() ->\n            Decoded = Getmail(\"image-attachment-only.eml\"),\n            ?assertEqual(5, tuple_size(Decoded)),\n            {Type, SubType, _Headers, _Properties, Body} = Decoded,\n            ?assertEqual({<<\"multipart\">>, <<\"mixed\">>}, {Type, SubType}),\n            ?assertEqual(1, length(Body)),\n            ?assertMatch([{<<\"image\">>, <<\"jpeg\">>, _, _, _}], Body),\n            [H | _] = Body,\n            [{<<\"image\">>, <<\"jpeg\">>, _, Parameters, _Image}] = Body,\n            ?assertEqual(?IMAGE_MD5, erlang:md5(element(5, H))),\n            ?assertEqual(<<\"inline\">>, maps:get(disposition, Parameters)),\n            ?assertEqual(\n                <<\"chili-pepper.jpg\">>, proplists:get_value(<<\"filename\">>, maps:get(disposition_params, Parameters))\n            ),\n            ?assertEqual(\n                <<\"chili-pepper.jpg\">>, proplists:get_value(<<\"name\">>, maps:get(content_type_params, Parameters))\n            )\n        end},\n        {\"message attachment only\", fun() ->\n            Decoded = Getmail(\"message-as-attachment.eml\"),\n            ?assertMatch({<<\"multipart\">>, <<\"mixed\">>, _, _, _}, Decoded),\n            [Body] = element(5, Decoded),\n            ?assertMatch({<<\"message\">>, <<\"rfc822\">>, _, _, _}, Body),\n            Subbody = element(5, Body),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, _}, Subbody),\n            ?assertEqual(<<\"This message contains only plain text.\\r\\n\">>, element(5, Subbody))\n        end},\n        {\"message, image, and rtf attachments.\", fun() ->\n            Decoded = Getmail(\"message-image-text-attachments.eml\"),\n            ?assertMatch({<<\"multipart\">>, <<\"mixed\">>, _, _, _}, Decoded),\n            ?assertEqual(3, length(element(5, Decoded))),\n            [Message, Rtf, Image] = element(5, Decoded),\n            ?assertMatch({<<\"message\">>, <<\"rfc822\">>, _, _, _}, Message),\n            Submessage = element(5, Message),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, <<\"This message contains only plain text.\\r\\n\">>}, Submessage),\n\n            ?assertMatch({<<\"text\">>, <<\"rtf\">>, _, _, _}, Rtf),\n            ?assertEqual(\n                <<\"{\\\\rtf1\\\\ansi\\\\ansicpg1252\\\\cocoartf949\\\\cocoasubrtf460\\r\\n{\\\\fonttbl\\\\f0\\\\fswiss\\\\fcharset0 Helvetica;}\\r\\n{\\\\colortbl;\\\\red255\\\\green255\\\\blue255;}\\r\\n\\\\margl1440\\\\margr1440\\\\vieww9000\\\\viewh8400\\\\viewkind0\\r\\n\\\\pard\\\\tx720\\\\tx1440\\\\tx2160\\\\tx2880\\\\tx3600\\\\tx4320\\\\tx5040\\\\tx5760\\\\tx6480\\\\tx7200\\\\tx7920\\\\tx8640\\\\ql\\\\qnatural\\\\pardirnatural\\r\\n\\r\\n\\\\f0\\\\fs24 \\\\cf0 This is a basic rtf file.}\">>,\n                element(5, Rtf)\n            ),\n\n            ?assertMatch({<<\"image\">>, <<\"jpeg\">>, _, _, _}, Image),\n            ?assertEqual(?IMAGE_MD5, erlang:md5(element(5, Image)))\n        end},\n        {\"alternative text/html with calendar attachment.\", fun() ->\n            Decoded = Getmail(\"message-text-html-attachment.eml\"),\n            ?assertMatch(\n                {<<\"multipart\">>, <<\"mixed\">>, _, _, [\n                    {<<\"multipart\">>, <<\"alternative\">>, _, _, [\n                        {<<\"text\">>, <<\"plain\">>, _, _, _},\n                        {<<\"text\">>, <<\"html\">>, _, _, _}\n                    ]},\n                    {<<\"text\">>, <<\"calendar\">>, _, _, _}\n                ]},\n                Decoded\n            )\n        end},\n        {\"Outlook 2007 with leading tabs in quoted-printable.\", fun() ->\n            Decoded = Getmail(\"outlook-2007.eml\"),\n            ?assertMatch({<<\"multipart\">>, <<\"alternative\">>, _, _, _}, Decoded)\n        end},\n        {\"The gamut\", fun() ->\n            % multipart/alternative\n            %\ttext/plain\n            %\tmultipart/mixed\n            %\t\ttext/html\n            %\t\tmessage/rf822\n            %\t\t\tmultipart/mixed\n            %\t\t\t\tmessage/rfc822\n            %\t\t\t\t\ttext/plain\n            %\t\ttext/html\n            %\t\tmessage/rtc822\n            %\t\t\ttext/plain\n            %\t\ttext/html\n            %\t\timage/jpeg\n            %\t\ttext/html\n            %\t\ttext/rtf\n            %\t\ttext/html\n            Decoded = Getmail(\"the-gamut.eml\"),\n            ?assertMatch({<<\"multipart\">>, <<\"alternative\">>, _, _, _}, Decoded),\n            ?assertEqual(2, length(element(5, Decoded))),\n            [Toptext, Topmultipart] = element(5, Decoded),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, _}, Toptext),\n            ?assertEqual(\n                <<\"This is rich text.\\r\\n\\r\\nThe list is html.\\r\\n\\r\\nAttchments:\\r\\nan email containing an attachment of an email.\\r\\nan email of only plain text.\\r\\nan image\\r\\nan rtf file.\\r\\n\">>,\n                element(5, Toptext)\n            ),\n            ?assertEqual(9, length(element(5, Topmultipart))),\n            [Html, Messagewithin, Brhtml, _Message, Brhtml, Image, Brhtml, Rtf, Brhtml] = element(5, Topmultipart),\n            ?assertMatch({<<\"text\">>, <<\"html\">>, _, _, _}, Html),\n            ?assertEqual(\n                <<\"<html><body style=\\\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \\\"><b>This</b> is <i>rich</i> text.<div><br></div><div>The list is html.</div><div><br></div><div>Attchments:</div><div><ul class=\\\"MailOutline\\\"><li>an email containing an attachment of an email.</li><li>an email of only plain text.</li><li>an image</li><li>an rtf file.</li></ul></div><div></div></body></html>\">>,\n                element(5, Html)\n            ),\n\n            ?assertMatch({<<\"message\">>, <<\"rfc822\">>, _, _, _}, Messagewithin),\n            %?assertEqual(1, length(element(5, Messagewithin))),\n            ?assertMatch(\n                {<<\"multipart\">>, <<\"mixed\">>, _, _, [\n                    {<<\"message\">>, <<\"rfc822\">>, _, _,\n                        {<<\"text\">>, <<\"plain\">>, _, _, <<\"This message contains only plain text.\\r\\n\">>}}\n                ]},\n                element(5, Messagewithin)\n            ),\n\n            ?assertMatch({<<\"image\">>, <<\"jpeg\">>, _, _, _}, Image),\n            ?assertEqual(?IMAGE_MD5, erlang:md5(element(5, Image))),\n\n            ?assertMatch({<<\"text\">>, <<\"rtf\">>, _, _, _}, Rtf),\n            ?assertEqual(\n                <<\"{\\\\rtf1\\\\ansi\\\\ansicpg1252\\\\cocoartf949\\\\cocoasubrtf460\\r\\n{\\\\fonttbl\\\\f0\\\\fswiss\\\\fcharset0 Helvetica;}\\r\\n{\\\\colortbl;\\\\red255\\\\green255\\\\blue255;}\\r\\n\\\\margl1440\\\\margr1440\\\\vieww9000\\\\viewh8400\\\\viewkind0\\r\\n\\\\pard\\\\tx720\\\\tx1440\\\\tx2160\\\\tx2880\\\\tx3600\\\\tx4320\\\\tx5040\\\\tx5760\\\\tx6480\\\\tx7200\\\\tx7920\\\\tx8640\\\\ql\\\\qnatural\\\\pardirnatural\\r\\n\\r\\n\\\\f0\\\\fs24 \\\\cf0 This is a basic rtf file.}\">>,\n                element(5, Rtf)\n            )\n        end},\n        {\"Plain text and 2 identical attachments\", fun() ->\n            Decoded = Getmail(\"plain-text-and-two-identical-attachments.eml\"),\n            ?assertMatch({<<\"multipart\">>, <<\"mixed\">>, _, _, _}, Decoded),\n            ?assertEqual(3, length(element(5, Decoded))),\n            [Plain, Attach1, Attach2] = element(5, Decoded),\n            ?assertEqual(Attach1, Attach2),\n            ?assertMatch({<<\"text\">>, <<\"plain\">>, _, _, _}, Plain),\n            ?assertEqual(<<\"This message contains only plain text.\\r\\n\">>, element(5, Plain))\n        end},\n        {\"no \\\\r\\\\n before first boundary\", fun() ->\n            {ok, Bin} = file:read_file(\"test/fixtures/html.eml\"),\n            Decoded = decode(Bin),\n            ?assertEqual(2, length(element(5, Decoded)))\n        end},\n        {\"permissive malformed folded multibyte header decoder\", fun() ->\n            {_, _, Headers, _, Body} = Getmail(\"malformed-folded-multibyte-header.eml\"),\n            ?assertEqual(<<\"Hello world\\n\">>, Body),\n            Subject =\n                <<78, 79, 68, 51, 50, 32, 83, 109, 97, 114, 116, 32, 83, 101, 99, 117, 114, 105, 116, 121, 32, 45, 32,\n                    208, 177, 208, 181, 209, 129, 208, 191, 208, 187, 208, 176, 209, 130, 208, 189, 208, 176, 209, 143,\n                    32, 208, 187, 208, 184, 209, 134, 208, 181, 208, 189, 208, 183, 208, 184, 209, 143>>,\n            ?assertEqual(Subject, proplists:get_value(<<\"Subject\">>, Headers))\n        end},\n        {\"decode headers of multipart messages\", fun() ->\n            {<<\"multipart\">>, _, _, _, [Inline, Attachment]} = Getmail(\"utf-attachment-name.eml\"),\n            {<<\"text\">>, _, _, _, InlineBody} = Inline,\n            {<<\"text\">>, _, _, ContentHeaders, _AttachmentBody} = Attachment,\n            ContentTypeName = proplists:get_value(\n                <<\"name\">>,\n                maps:get(\n                    content_type_params, ContentHeaders\n                )\n            ),\n            DispositionName = proplists:get_value(\n                <<\"filename\">>,\n                maps:get(\n                    disposition_params, ContentHeaders\n                )\n            ),\n\n            ?assertEqual(<<\"Hello\\r\\n\">>, InlineBody),\n            ?assert(ContentTypeName == DispositionName),\n            % Take the filename as a literal, to prevent character set issues with Erlang\n            % In utf-8 the filename is:\"тестовый файл.txt\"\n            Filename =\n                <<209, 130, 208, 181, 209, 129, 209, 130, 208, 190, 208, 178, 209, 139, 208, 185, 32, 209, 132, 208,\n                    176, 208, 185, 208, 187, 46, 116, 120, 116>>,\n            ?assertEqual(Filename, ContentTypeName),\n            ?assertEqual(Filename, DispositionName)\n        end},\n        {\"testcase1\", fun() ->\n            Multipart = <<\"multipart\">>,\n            Alternative = <<\"alternative\">>,\n            Related = <<\"related\">>,\n            Mixed = <<\"mixed\">>,\n            Text = <<\"text\">>,\n            Html = <<\"html\">>,\n            Plain = <<\"plain\">>,\n            Message = <<\"message\">>,\n            Ref822 = <<\"rfc822\">>,\n            Image = <<\"image\">>,\n            Jpeg = <<\"jpeg\">>,\n            %Imagemd5 = <<69,175,198,78,52,72,6,233,147,22,50,137,128,180,169,50>>,\n            Imagemd5 = <<179, 151, 42, 139, 78, 14, 182, 78, 24, 160, 123, 221, 217, 14, 141, 5>>,\n            Decoded = Getmail(\"testcase1\"),\n            ?assertMatch({Multipart, Mixed, _, _, [_, _]}, Decoded),\n            [Multi1, Message1] = element(5, Decoded),\n            ?assertMatch({Multipart, Alternative, _, _, [_, _]}, Multi1),\n            [Plain1, Html1] = element(5, Multi1),\n            ?assertMatch({Text, Plain, _, _, _}, Plain1),\n            ?assertMatch({Text, Html, _, _, _}, Html1),\n            ?assertMatch({Message, Ref822, _, _, _}, Message1),\n            Multi2 = element(5, Message1),\n            ?assertMatch({Multipart, Alternative, _, _, [_, _]}, Multi2),\n            [Plain2, Related1] = element(5, Multi2),\n            ?assertMatch({Text, Plain, _, _, _}, Plain2),\n            ?assertMatch({Multipart, Related, _, _, [_, _]}, Related1),\n            [Html2, Image1] = element(5, Related1),\n            ?assertMatch({Text, Html, _, _, _}, Html2),\n            ?assertMatch({Image, Jpeg, _, _, _}, Image1),\n            Resimage = erlang:md5(element(5, Image1)),\n            ?assertEqual(Imagemd5, Resimage)\n        end},\n        {\"testcase2\", fun() ->\n            Multipart = <<\"multipart\">>,\n            Alternative = <<\"alternative\">>,\n            Mixed = <<\"mixed\">>,\n            Text = <<\"text\">>,\n            Html = <<\"html\">>,\n            Plain = <<\"plain\">>,\n            Message = <<\"message\">>,\n            Ref822 = <<\"rfc822\">>,\n            Application = <<\"application\">>,\n            Octetstream = <<\"octet-stream\">>,\n            Decoded = Getmail(\"testcase2\"),\n            ?assertMatch({Multipart, Mixed, _, _, [_, _, _]}, Decoded),\n            [Plain1, Stream1, Message1] = element(5, Decoded),\n            ?assertMatch({Text, Plain, _, _, _}, Plain1),\n            ?assertMatch({Application, Octetstream, _, _, _}, Stream1),\n            ?assertMatch({Message, Ref822, _, _, _}, Message1),\n            Multi1 = element(5, Message1),\n            ?assertMatch({Multipart, Alternative, _, _, [_, _]}, Multi1),\n            [Plain2, Html1] = element(5, Multi1),\n            ?assertMatch({Text, Plain, _, _, _}, Plain2),\n            ?assertMatch({Text, Html, _, _, _}, Html1)\n        end}\n    ].\n\ndecode_quoted_printable_test_() ->\n    [\n        {\"bleh\", fun() ->\n            ?assertEqual(<<\"!\">>, decode_quoted_printable(<<\"=21\">>)),\n            ?assertEqual(<<\"!!\">>, decode_quoted_printable(<<\"=21=21\">>)),\n            ?assertEqual(<<\"=:=\">>, decode_quoted_printable(<<\"=3D:=3D\">>)),\n            ?assertEqual(\n                <<\"Thequickbrownfoxjumpedoverthelazydog.\">>,\n                decode_quoted_printable(<<\"Thequickbrownfoxjumpedoverthelazydog.\">>)\n            )\n        end},\n        {\"lowercase bleh\", fun() ->\n            ?assertEqual(<<\"=:=\">>, decode_quoted_printable(<<\"=3d:=3d\">>))\n        end},\n        {\"input with spaces\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.\">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\">>)\n            )\n        end},\n        {\"input with tabs\", fun() ->\n            ?assertEqual(\n                <<\"The\\tquick brown fox jumped over\\tthe lazy dog.\">>,\n                decode_quoted_printable(<<\"The\\tquick brown fox jumped over\\tthe lazy dog.\">>)\n            )\n        end},\n        {\"input with trailing spaces\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.\">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       \">>)\n            )\n        end},\n        {\"input with non-strippable trailing whitespace\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.        \">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       =20\">>)\n            ),\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.       \\t\">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       =09\">>)\n            ),\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.\\t \\t \\t \\t \">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\\t \\t \\t =09=20\">>)\n            ),\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.\\t \\t \\t \\t \">>,\n                decode_quoted_printable(\n                    <<\"The quick brown fox jumped over the lazy dog.\\t \\t \\t =09=20\\t                  \\t\">>\n                )\n            )\n        end},\n        {\"input with trailing tabs\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.\">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\\t\\t\\t\\t\\t\">>)\n            )\n        end},\n        {\"soft new line\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.       \">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       =\">>)\n            )\n        end},\n        {\"soft new line with trailing whitespace\", fun() ->\n            ?assertEqual(\n                <<\"The quick brown fox jumped over the lazy dog.       \">>,\n                decode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       =  \t\">>)\n            )\n        end},\n        {\"multiline stuff\", fun() ->\n            ?assertEqual(\n                <<\"Now's the time for all folk to come to the aid of their country.\">>,\n                decode_quoted_printable(\n                    <<\"Now's the time =\\r\\nfor all folk to come=\\r\\n to the aid of their country.\">>\n                )\n            ),\n            ?assertEqual(\n                <<\"Now's the time\\r\\nfor all folk to come\\r\\n to the aid of their country.\">>,\n                decode_quoted_printable(<<\"Now's the time\\r\\nfor all folk to come\\r\\n to the aid of their country.\">>)\n            ),\n            ?assertEqual(<<\"hello world\">>, decode_quoted_printable(<<\"hello world\">>)),\n            ?assertEqual(<<\"hello\\r\\n\\r\\nworld\">>, decode_quoted_printable(<<\"hello\\r\\n\\r\\nworld\">>))\n        end},\n        {\"invalid input\", fun() ->\n            ?assertThrow(badchar, decode_quoted_printable(<<\"=21=G1\">>)),\n            ?assertThrow(badchar, decode_quoted_printable(<<\"=21=D1 = g \">>))\n        end},\n        %% TODO zotonic's iconv throws eilseq here.\n        % {\"out of range characters should be stripped\",\n        % \tfun() ->\n        % \t\t% character 150 is en-dash in windows 1252\n        % \t\t?assertEqual(<<\"Foo  bar\"/utf8>>, decode_body(<<\"quoted-printable\">>, <<\"Foo \", 150, \" bar\">>, \"US-ASCII\", \"UTF-8//IGNORE\"))\n        % \tend\n        % },\n        {\"out of range character in alternate charset should be converted\", fun() ->\n            % character 150 is en-dash in windows 1252\n            ?assertEqual(\n                <<\"Foo \", 226, 128, 147, \" bar\">>,\n                decode_body(<<\"quoted-printable\">>, <<\"Foo \", 150, \" bar\">>, \"Windows-1252\", \"UTF-8//IGNORE\")\n            )\n        end},\n        {\"out of range character in alternate charset with no destination encoding should be stripped\", fun() ->\n            % character 150 is en-dash in windows 1252\n            ?assertEqual(\n                <<\"Foo  bar\">>, decode_body(<<\"quoted-printable\">>, <<\"Foo \", 150, \" bar\">>, \"Windows-1252\", none)\n            )\n        end},\n        {\"out of range character in alternate charset with no source encoding should be stripped\", fun() ->\n            % character 150 is en-dash in windows 1252\n            ?assertEqual(\n                <<\"Foo  bar\">>, decode_body(<<\"quoted-printable\">>, <<\"Foo \", 150, \" bar\">>, undefined, \"UTF-8\")\n            )\n        end},\n        {\"almost correct chatsets should work, eg. 'UTF8' instead of 'UTF-8'\", fun() ->\n            % character 150 is en-dash in windows 1252\n            ?assertEqual(<<\"Foo  bar\">>, decode_body(<<\"quoted-printable\">>, <<\"Foo  bar\">>, <<\"UTF8\">>, \"UTF-8\")),\n            ?assertEqual(<<\"Foo  bar\">>, decode_body(<<\"quoted-printable\">>, <<\"Foo  bar\">>, <<\"utf8\">>, \"UTF-8\"))\n        end}\n    ].\n\nvalid_smtp_mime_7bit_test() ->\n    ?assert(valid_7bit(<<>>)),\n    ?assert(valid_7bit(<<\"abcdefghijklmnopqrstuvwxyz0123456789\">>)),\n    ?assert(valid_7bit(<<\"abc\\r\\ndef\">>)),\n    AllValidRange =\n        (lists:seq(1, $\\n - 1) ++\n            lists:seq($\\n + 1, $\\r - 1) ++\n            lists:seq($\\r + 1, 127)),\n    ?assert(valid_7bit(list_to_binary(AllValidRange))),\n    ?assertNot(valid_7bit(<<\"\\n\">>)),\n    ?assertNot(valid_7bit(<<\"\\r\">>)),\n    ?assertNot(valid_7bit(<<\"abc\\ndef\">>)),\n    ?assertNot(valid_7bit(<<\"abc\\rdef\">>)),\n    ?assertNot(valid_7bit(<<\"abc\\n\\rdef\">>)),\n    ?assertNot(valid_7bit(<<128, 200, 255>>)),\n    ?assertNot(valid_7bit(<<0, 0, 0>>)),\n    ?assertNot(valid_7bit(<<\"hello\", 128, 0, 200>>)),\n    %% Long lines\n    Line800 = binary:copy(<<$a>>, 800),\n    ?assertNot(has_lines_over_998(Line800)),\n    Many800Lines = list_to_binary(lists:join(\"\\r\\n\", lists:duplicate(10, Line800))),\n    ?assertNot(has_lines_over_998(Many800Lines)),\n    Line1000 = binary:copy(<<$a>>, 1000),\n    ?assert(has_lines_over_998(Line1000)),\n    Many1000Lines = list_to_binary(lists:join(\"\\r\\n\", lists:duplicate(10, Line1000))),\n    ?assert(has_lines_over_998(Many1000Lines)),\n    ?assert(has_lines_over_998(<<Line800/binary, \"\\r\\n\", Line1000/binary>>)).\n\nencode_quoted_printable_test_() ->\n    [\n        {\"bleh\", fun() ->\n            ?assertEqual([<<\"!\">>], encode_quoted_printable(<<\"!\">>)),\n            ?assertEqual([<<\"!!\">>], encode_quoted_printable(<<\"!!\">>)),\n            ?assertEqual([<<\"=3D:=3D\">>], encode_quoted_printable(<<\"=:=\">>)),\n            ?assertEqual(\n                [<<\"Thequickbrownfoxjumpedoverthelazydog.\">>],\n                encode_quoted_printable(<<\"Thequickbrownfoxjumpedoverthelazydog.\">>)\n            )\n        end},\n        {\"input with spaces\", fun() ->\n            ?assertEqual(\n                [<<\"The quick brown fox jumped over the lazy dog.\">>],\n                encode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\">>)\n            )\n        end},\n        {\"input with tabs\", fun() ->\n            ?assertEqual(\n                [<<\"The\\tquick brown fox jumped over\\tthe lazy dog.\">>],\n                encode_quoted_printable(<<\"The\\tquick brown fox jumped over\\tthe lazy dog.\">>)\n            )\n        end},\n        {\"input with trailing spaces\", fun() ->\n            ?assertEqual(\n                [<<\"The quick brown fox jumped over the lazy dog.      =20\\r\\n\">>],\n                encode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       \\r\\n\">>)\n            ),\n            ?assertEqual(\n                [<<\"The quick brown fox jumped over the lazy dog.      =20\">>],\n                encode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.       \">>)\n            )\n        end},\n        {\"input with trailing tabs\", fun() ->\n            ?assertEqual(\n                [<<\"The quick brown fox jumped over the lazy dog.\t=09\\r\\n\">>],\n                encode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\t\t\\r\\n\">>)\n            ),\n            ?assertEqual(\n                [<<\"The quick brown fox jumped over the lazy dog.\t=09\">>],\n                encode_quoted_printable(<<\"The quick brown fox jumped over the lazy dog.\t\t\">>)\n            )\n        end},\n        {\"input with non-ascii characters\", fun() ->\n            ?assertEqual(\n                [<<\"There's some n=F8n-=E1scii st=FCff in here\\r\\n\">>],\n                encode_quoted_printable(<<\"There's some n\", 248, \"n-\", 225, \"scii st\", 252, \"ff in here\\r\\n\">>)\n            )\n        end},\n        {\"input with invisible non-ascii characters\", fun() ->\n            ?assertEqual(\n                [<<\"There's some stuff=C2=A0in=C2=A0here\\r\\n\">>],\n                encode_quoted_printable(<<\"There's some stuff in here\\r\\n\"/utf8>>)\n            )\n        end},\n        {\"add soft newlines\", fun() ->\n            ?assertEqual(\n                [\n                    <<\"The quick brown fox jumped over the lazy dog. The quick brown fox jumped =\\r\\nover the lazy dog.\">>\n                ],\n                encode_quoted_printable(\n                    <<\"The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_ov=\\r\\ner_the_lazy_dog.\">>\n                ],\n                encode_quoted_printable(\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_over_the_lazy_dog.\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_o=\\r\\n=3Dver_the_lazy_dog.\">>\n                ],\n                encode_quoted_printable(\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_o=ver_the_lazy_dog.\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_=\\r\\n=3Dover_the_lazy_dog.\">>\n                ],\n                encode_quoted_printable(\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_=over_the_lazy_dog.\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_o =\\r\\nver_the_lazy_dog.\">>\n                ],\n                encode_quoted_printable(\n                    <<\"The_quick_brown_fox_jumped_over_the_lazy_dog._The_quick_brown_fox_jumped_o ver_the_lazy_dog.\">>\n                )\n            )\n        end},\n        {\"soft newline edge cases\", fun() ->\n            ?assertEqual(\n                [\n                    <<\n                        \"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345=\\r\\n\"\n                        \"=20\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 \">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345=\\r\\n\"\n                        \"=20\\r\\n\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345 \\r\\n\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345=\\r\\n\"\n                        \"=09\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345\t\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345=\\r\\n\"\n                        \"=09\\r\\n\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345\t\\r\\n\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \"123456789 123456789 123456789 123456789 123456789 123456789 123456789 =\\r\\n\"\n                        \"12345=3D\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345=\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \" 23456789012345678901234567890123456789012345678901234567890123456789012345=\\r\\n\"\n                        \"=20\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\" 23456789012345678901234567890123456789012345678901234567890123456789012345 \">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \" =\\r\\n\"\n                        \"234567890123456789012345678901234567890123456789012345678901234567890123456\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\" 234567890123456789012345678901234567890123456789012345678901234567890123456\">>\n                )\n            ),\n            ?assertEqual(\n                [\n                    <<\n                        \" 23456789012345678901234567890123456789012345678901234567890123456789012345=\\r\\n\"\n                        \"=3D\"\n                    >>\n                ],\n                encode_quoted_printable(\n                    <<\" 23456789012345678901234567890123456789012345678901234567890123456789012345=\">>\n                )\n            )\n        end}\n    ].\n\nencode_parameter_test_() ->\n    [\n        {\"Token\", fun() ->\n            ?assertEqual(\n                [<<\"a=abcdefghijklmnopqrstuvwxyz$%&*#!\">>],\n                encode_parameters([{<<\"a\">>, <<\"abcdefghijklmnopqrstuvwxyz$%&*#!\">>}])\n            ),\n            ?assertEqual(\n                [<<\"a=12345678901234567890123456789012345678901234567890123456789012345678901234\">>],\n                encode_parameters([\n                    {<<\"a\">>, <<\"12345678901234567890123456789012345678901234567890123456789012345678901234\">>}\n                ])\n            ),\n            ?assertEqual(\n                [\n                    <<\"a*0=123456789012345678901234567890123456789012345678901234567890123456789012\">>,\n                    <<\"a*1=345\">>\n                ],\n                encode_parameters([\n                    {<<\"a\">>, <<\"123456789012345678901234567890123456789012345678901234567890123456789012345\">>}\n                ])\n            )\n        end},\n        {\"TSpecial\", fun() ->\n            Special = \" ()<>@,;:/[]?=\",\n            [\n                ?assertEqual([<<\"a=\", $\", C, $\">>], encode_parameters([{<<\"a\">>, <<C>>}]))\n             || C <- Special\n            ],\n            ?assertEqual([<<\"a=\", $\", $\\\\, $\", $\">>], encode_parameters([{<<\"a\">>, <<$\">>}])),\n            ?assertEqual([<<\"a=\", $\", $\\\\, $\\\\, $\">>], encode_parameters([{<<\"a\">>, <<$\\\\>>}])),\n            ?assertEqual(\n                [<<\"a=\\\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12\\\"\">>],\n                encode_parameters([\n                    {<<\"a\">>, <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 12\">>}\n                ])\n            ),\n            ?assertEqual(\n                [\n                    <<\"a*0=\\\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 \\\"\">>,\n                    <<\"a*1=\\\"123\\\"\">>\n                ],\n                encode_parameters([\n                    {<<\"a\">>, <<\"123456789 123456789 123456789 123456789 123456789 123456789 123456789 123\">>}\n                ])\n            )\n        end},\n        {\"RFC2231 encoded\", fun() ->\n            ?assertEqual(\n                [<<\"a*=''1234567%001234567%001234567%001234567%001234567%001234567%001234567%001\">>],\n                encode_parameters([\n                    {<<\"a\">>,\n                        <<\"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\",\n                            0, \"1\">>}\n                ])\n            ),\n            ?assertEqual(\n                [\n                    <<\"a*0*=''1234567%001234567%001234567%001234567%001234567%001234567%001234567\">>,\n                    <<\"a*1*=%0012\">>\n                ],\n                encode_parameters([\n                    {<<\"a\">>,\n                        <<\"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\", 0, \"1234567\",\n                            0, \"12\">>}\n                ])\n            )\n        end},\n        {\"RFC2231 encoded with UTF-8\", fun() ->\n            ?assertEqual(\n                [<<\"a*=UTF-8''1234%C2%A01234%C2%A01234%C2%A01234%C2%A01234%C2%A01234%C2%A01234\">>],\n                encode_parameters([\n                    {<<\"a\">>,\n                        <<\"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0,\n                            \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\">>}\n                ])\n            ),\n            ?assertEqual(\n                [\n                    <<\"a*0*=UTF-8''1234%C2%A01234%C2%A01234%C2%A01234%C2%A01234%C2%A01234%C2%A01234\">>,\n                    <<\"a*1*=%C2%A0\">>\n                ],\n                encode_parameters([\n                    {<<\"a\">>,\n                        <<\"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0,\n                            \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0, \"1234\", 16#c2, 16#a0>>}\n                ])\n            )\n        end}\n    ].\n\nrfc2047_decode_test_() ->\n    [\n        {\"Simple tests\", fun() ->\n            ?assertEqual(\n                <<\"Keith Moore <moore@cs.utk.edu>\"/utf8>>,\n                decode_header(<<\"=?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>\">>, \"utf-8\")\n            ),\n            ?assertEqual(\n                <<\"Keld Jørn Simonsen <keld@dkuug.dk>\"/utf8>>,\n                decode_header(<<\"=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>\">>, \"utf-8\")\n            ),\n            ?assertEqual(\n                <<\"Olle Järnefors <ojarnef@admin.kth.se>\"/utf8>>,\n                decode_header(<<\"=?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>\">>, \"utf-8\")\n            ),\n            ?assertEqual(\n                <<\"André Pirard <PIRARD@vm1.ulg.ac.be>\"/utf8>>,\n                decode_header(<<\"=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>\">>, \"utf-8\")\n            )\n        end},\n        {\"encoded words separated by whitespace should have whitespace removed\", fun() ->\n            ?assertEqual(\n                <<\"If you can read this you understand the example.\">>,\n                decode_header(\n                    <<\"=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\">>,\n                    \"utf-8\"\n                )\n            ),\n            ?assertEqual(<<\"ab\">>, decode_header(<<\"=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=\">>, \"utf-8\")),\n            ?assertEqual(<<\"ab\">>, decode_header(<<\"=?ISO-8859-1?Q?a?=  =?ISO-8859-1?Q?b?=\">>, \"utf-8\")),\n            ?assertEqual(\n                <<\"ab\">>,\n                decode_header(\n                    <<\n                        \"=?ISO-8859-1?Q?a?=\\n\"\n                        \"\t\t=?ISO-8859-1?Q?b?=\"\n                    >>,\n                    \"utf-8\"\n                )\n            )\n        end},\n        {\"underscores expand to spaces\", fun() ->\n            ?assertEqual(<<\"a b\">>, decode_header(<<\"=?ISO-8859-1?Q?a_b?=\">>, \"utf-8\")),\n            ?assertEqual(<<\"a b\">>, decode_header(<<\"=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=\">>, \"utf-8\"))\n        end},\n        {\"edgecases\", fun() ->\n            ?assertEqual(\n                <<\"this is some text\">>, decode_header(<<\"=?iso-8859-1?q?this=20is=20some=20text?=\">>, \"utf-8\")\n            ),\n            ?assertEqual(\n                <<\"=?iso-8859-1?q?this is some text?=\">>,\n                decode_header(<<\"=?iso-8859-1?q?this is some text?=\">>, \"utf-8\")\n            )\n        end},\n        {\"invalid character sequence handling\", fun() ->\n            ?assertException(\n                throw,\n                eilseq,\n                decode_header(<<\"=?us-ascii?B?dGhpcyBjb250YWlucyBhIGNvcHlyaWdodCCpIHN5bWJvbA==?=\">>, \"utf-8\")\n            ),\n            %?assertEqual(<<\"this contains a copyright  symbol\"/utf8>>, decode_header(<<\"=?us-ascii?B?dGhpcyBjb250YWlucyBhIGNvcHlyaWdodCCpIHN5bWJvbA==?=\">>, \"utf-8//IGNORE\")),\n            ?assertEqual(\n                <<\"this contains a copyright © symbol\"/utf8>>,\n                decode_header(<<\"=?iso-8859-1?B?dGhpcyBjb250YWlucyBhIGNvcHlyaWdodCCpIHN5bWJvbA==?=\">>, \"utf-8//IGNORE\")\n            )\n        end},\n        {\"multiple unicode email addresses\", fun() ->\n            ?assertEqual(\n                <<\n                    \"Jacek Złydach <jacek.zlydach@erlang-solutions.com>, \"\n                    \"chak de planet óóóó <jz@erlang-solutions.com>, \"\n                    \"Jacek Złydach <jacek.zlydach@erlang-solutions.com>, \"\n                    \"chak de planet óóóó <jz@erlang-solutions.com>\"/utf8\n                >>,\n                decode_header(\n                    <<\n                        \"=?UTF-8?B?SmFjZWsgWsWCeWRhY2g=?= <jacek.zlydach@erlang-solutions.com>, \"\n                        \"=?UTF-8?B?Y2hhayBkZSBwbGFuZXQgw7PDs8Ozw7M=?= <jz@erlang-solutions.com>, \"\n                        \"=?UTF-8?B?SmFjZWsgWsWCeWRhY2g=?= <jacek.zlydach@erlang-solutions.com>, \"\n                        \"=?UTF-8?B?Y2hhayBkZSBwbGFuZXQgw7PDs8Ozw7M=?= <jz@erlang-solutions.com>\"\n                    >>,\n                    \"utf-8\"\n                )\n            )\n        end},\n        {\"decode something I encoded myself\", fun() ->\n            A = <<\"Jacek Złydach <jacek.zlydach@erlang-solutions.com>\"/utf8>>,\n            ?assertEqual(A, decode_header(rfc2047_utf8_encode(A), \"utf-8\"))\n        end}\n    ].\n\nrfc2047_utf8_encode_test_() ->\n    [\n        {\"Q-Encoding\", fun() ->\n            ?assertEqual(\n                <<\"=?UTF-8?Q?abcdefghijklmnopqrstuvwxyz?=\">>,\n                rfc2047_utf8_encode(q, <<\"abcdefghijklmnopqrstuvwxyz\">>, <<>>, 0, <<\" \">>)\n            ),\n            ?assertEqual(\n                <<\"=?UTF-8?Q?ABCDEFGHIJKLMNOPQRSTUVWXYZ?=\">>,\n                rfc2047_utf8_encode(q, <<\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\">>, <<>>, 0, <<\" \">>)\n            ),\n            ?assertEqual(<<\"=?UTF-8?Q?0123456789?=\">>, rfc2047_utf8_encode(q, <<\"0123456789\">>, <<>>, 0, <<\" \">>)),\n            ?assertEqual(<<\"=?UTF-8?Q?!*+-/?=\">>, rfc2047_utf8_encode(q, <<\"!*+-/\">>, <<>>, 0, <<\" \">>)),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?Q?This_text_encodes_to_more_than_63_bytes=2E_Therefore=2C_it_shou?=\\r\\n\"\n                    \" =?UTF-8?Q?ld_be_encoded_in_multiple_encoded_words=2E?=\"\n                >>,\n                rfc2047_utf8_encode(\n                    q,\n                    <<\"This text encodes to more than 63 bytes. Therefore, it should be encoded in multiple encoded words.\">>,\n                    <<>>,\n                    0,\n                    <<\" \">>\n                )\n            ),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?Q?This_text_encodes_to_more_than_63_bytes_with_offset_f?=\\r\\n\"\n                    \"\\t=?UTF-8?Q?or_a_parameter=2E_Therefore=2C_it_should_be_encoded_in_multipl?=\\r\\n\"\n                    \"\\t=?UTF-8?Q?e_encoded_words=2E?=\"\n                >>,\n                rfc2047_utf8_encode(\n                    q,\n                    <<\n                        \"This text encodes to more than 63 bytes with offset for a parameter. \"\n                        \"Therefore, it should be encoded in multiple encoded words.\"\n                    >>,\n                    <<>>,\n                    10,\n                    <<\"\\t\">>\n                )\n            ),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?Q?We_place_an_UTF8_4byte_character_over_the_breaking_point_here_?=\\r\\n\"\n                    \" =?UTF-8?Q?=F0=9F=80=84?=\"\n                >>,\n                rfc2047_utf8_encode(\n                    q,\n                    <<\"We place an UTF8 4byte character over the breaking point here \", 16#F0, 16#9F, 16#80, 16#84>>,\n                    <<>>,\n                    0,\n                    <<\" \">>\n                )\n            )\n        end},\n        {\"B-Encoding\", fun() ->\n            ?assertEqual(\n                <<\"=?UTF-8?B?U29tZSBzaG9ydCB0ZXh0Lg==?=\">>,\n                rfc2047_utf8_encode(b, <<\"Some short text.\">>, <<>>, 0, <<\" \">>)\n            ),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?B?VGhpcyB0ZXh0IGVuY29kZXMgdG8gbW9yZSB0aGFuIDYzIGJ5dGVzLiBUaGVy?=\\r\\n\"\n                    \" =?UTF-8?B?ZWZvcmUsIGl0IHNob3VsZCBiZSBlbmNvZGVkIGluIG11bHRpcGxlIGVuY29k?=\\r\\n\"\n                    \" =?UTF-8?B?ZWQgd29yZHMu?=\"\n                >>,\n                rfc2047_utf8_encode(\n                    b,\n                    <<\"This text encodes to more than 63 bytes. Therefore, it should be encoded in multiple encoded words.\">>,\n                    <<>>,\n                    1,\n                    <<\" \">>\n                )\n            ),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?B?AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKiss?=\\r\\n\"\n                    \" =?UTF-8?B?LS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZ?=\\r\\n\"\n                    \" =?UTF-8?B?WltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn8=?=\"\n                >>,\n                rfc2047_utf8_encode(b, <<<<X>> || X <- lists:seq(0, 16#7F)>>, <<>>, 1, <<\" \">>)\n            ),\n            ?assertEqual(\n                <<\n                    \"=?UTF-8?B?UGxhY2UgYW4gVVRGOCA0Ynl0ZSBjaGFyYWN0ZXIgYXQgdGhlIGJyZWFr?=\\r\\n\"\n                    \" =?UTF-8?B?8J+AhA==?=\"\n                >>,\n                rfc2047_utf8_encode(\n                    b, <<\"Place an UTF8 4byte character at the break\", 16#F0, 16#9F, 16#80, 16#84>>, <<>>, 1, <<\" \">>\n                )\n            )\n        end},\n        {\"Pick encoding\", fun() ->\n            ?assertEqual(<<\"asdf\">>, rfc2047_utf8_encode(<<\"asdf\">>)),\n            ?assertEqual(<<\"=?UTF-8?Q?x=09?=\">>, rfc2047_utf8_encode(<<\"x\\t\">>)),\n            ?assertEqual(<<\"=?UTF-8?B?CXgJ?=\">>, rfc2047_utf8_encode(<<\"\\tx\\t\">>))\n        end}\n    ].\n\nencoding_test_() ->\n    Getmail = fun(File) ->\n        {ok, Email} = file:read_file(filename:join(\"test/fixtures/\", File)),\n        decode(Email)\n    end,\n    [\n        {\"Simple email\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>},\n                        {<<\"Message-ID\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"MIME-Version\">>, <<\"1.0\">>},\n                        {<<\"Date\">>, <<\"Sun, 01 Nov 2009 14:44:47 +0200\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result =\n                <<\"From: me@example.com\\r\\nTo: you@example.com\\r\\nSubject: This is a test\\r\\nMessage-ID: <abcd@example.com>\\r\\nMIME-Version: 1.0\\r\\nDate: Sun, 01 Nov 2009 14:44:47 +0200\\r\\n\\r\\nThis is a plain message\">>,\n            ?assertEqual(Result, encode(Email))\n        end},\n        {\"Email with UTF-8 characters\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"Subject\">>, <<\"Fræderik Hølljen\"/utf8>>},\n                        {<<\"From\">>, <<\"Fræderik Hølljen <me@example.com>\"/utf8>>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Message-ID\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"MIME-Version\">>, <<\"1.0\">>},\n                        {<<\"Date\">>, <<\"Sun, 01 Nov 2009 14:44:47 +0200\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result =\n                <<\"Subject: =?UTF-8?Q?Fr=C3=A6derik_H=C3=B8lljen?=\\r\\nFrom: =?UTF-8?Q?Fr=C3=A6derik_H=C3=B8lljen?= <me@example.com>\\r\\nTo: you@example.com\\r\\nMessage-ID: <abcd@example.com>\\r\\nMIME-Version: 1.0\\r\\nDate: Sun, 01 Nov 2009 14:44:47 +0200\\r\\n\\r\\nThis is a plain message\">>,\n            ?assertEqual(Result, encode(Email))\n        end},\n        {\"Email with UTF-8 in attachment filename.\", fun() ->\n            FileName = <<\n                \"Čia labai ilgas el. laiško priedo pavadinimas su \"/utf8,\n                \"lietuviškomis ar kokiomis kitomis ne ascii raidėmis.pdf\"/utf8\n            >>,\n            Email =\n                {<<\"multipart\">>, <<\"mixed\">>,\n                    [\n                        {<<\"From\">>, <<\"k.petrauskas@erisata.lt\">>},\n                        {<<\"Subject\">>, <<\"Čiobiškis\"/utf8>>},\n                        {<<\"Date\">>, <<\"Thu, 17 Dec 2020 20:12:33 +0200\">>},\n                        {<<\"Message-ID\">>, <<\"<47a08b7ff7d305087877361ca8eea1db@karolis.erisata.lt>\">>}\n                    ],\n                    #{\n                        content_type_params => [\n                            {<<\"boundary\">>, <<\"_=boundary-123=_\">>}\n                        ]\n                    },\n                    [\n                        {<<\"application\">>, <<\"pdf\">>, [],\n                            #{\n                                content_type_params => [\n                                    {<<\"name\">>, FileName},\n                                    {<<\"disposition\">>, <<\"attachment\">>}\n                                ],\n                                disposition => <<\"attachment\">>,\n                                disposition_params => [{<<\"filename\">>, FileName}]\n                            },\n                            <<\"data\">>}\n                    ]},\n            Result = <<\n                \"From: k.petrauskas@erisata.lt\\r\\n\"\n                \"Subject: =?UTF-8?Q?=C4=8Ciobi=C5=A1kis?=\\r\\n\"\n                \"Date: Thu, 17 Dec 2020 20:12:33 +0200\\r\\n\"\n                \"Message-ID: <47a08b7ff7d305087877361ca8eea1db@karolis.erisata.lt>\\r\\n\"\n                \"Content-Type: multipart/mixed;\\r\\n\"\n                \"\\tboundary=\\\"_=boundary-123=_\\\"\\r\\n\"\n                \"MIME-Version: 1.0\\r\\n\"\n                \"\\r\\n\"\n                \"\\r\\n\"\n                \"--_=boundary-123=_\\r\\n\"\n                \"Content-Type: application/pdf;\\r\\n\"\n                \"\\tname*0*=UTF-8''%C4%8Cia%20labai%20ilgas%20el.%20lai%C5%A1ko%20priedo%20pavad;\\r\\n\"\n                \"\\tname*1*=inimas%20su%20lietuvi%C5%A1komis%20ar%20kokiomis%20kitomis%20ne%20as;\\r\\n\"\n                \"\\tname*2*=cii%20raid%C4%97mis.pdf;\\r\\n\"\n                \"\\tdisposition=attachment\\r\\n\"\n                \"Content-Disposition: attachment;\\r\\n\"\n                \"\\tfilename*0*=UTF-8''%C4%8Cia%20labai%20ilgas%20el.%20lai%C5%A1ko%20priedo%20p;\\r\\n\"\n                \"\\tfilename*1*=avadinimas%20su%20lietuvi%C5%A1komis%20ar%20kokiomis%20kitomis;\\r\\n\"\n                \"\\tfilename*2*=%20ne%20ascii%20raid%C4%97mis.pdf\\r\\n\"\n                \"\\r\\n\"\n                \"data\\r\\n\"\n                \"--_=boundary-123=_--\\r\\n\"\n            >>,\n            ?assertEqual(Result, encode(Email))\n        end},\n        {\"Email with special chars in From\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"\\\"Admin & ' ( \\\\\\\"hallo\\\\\\\" ) ; , [ ] WS\\\" <a@example.com>\">>},\n                        {<<\"Message-ID\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"MIME-Version\">>, <<\"1.0\">>},\n                        {<<\"Date\">>, <<\"Sun, 01 Nov 2009 14:44:47 +0200\">>}\n                    ],\n                    #{}, <<\"This is a plain message\">>},\n            Result =\n                <<\n                    \"From: \\\"Admin & ' ( \\\\\\\"hallo\\\\\\\" ) ; , [ ] WS\\\" <a@example.com>\\r\\n\"\n                    \"Message-ID: <abcd@example.com>\\r\\n\"\n                    \"MIME-Version: 1.0\\r\\n\"\n                    \"Date: Sun, 01 Nov 2009 14:44:47 +0200\\r\\n\"\n                    \"\\r\\n\"\n                    \"This is a plain message\"\n                >>,\n            ?assertEqual(Result, encode(Email))\n        end},\n        {\"multipart/alternative email\", fun() ->\n            Email =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>},\n                        {<<\"MIME-Version\">>, <<\"1.0\">>},\n                        {<<\"Content-Type\">>, <<\"multipart/alternative; boundary=wtf-123234234\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"boundary\">>, <<\"wtf-123234234\">>}],\n                        disposition => <<\"inline\">>,\n                        disposition_params => []\n                    },\n                    [\n                        {<<\"text\">>, <<\"plain\">>,\n                            [\n                                {<<\"Content-Type\">>, <<\"text/plain;charset=US-ASCII;format=flowed\">>},\n                                {<<\"Content-Transfer-Encoding\">>, <<\"7bit\">>}\n                            ],\n                            #{\n                                content_type_params =>\n                                    [\n                                        {<<\"charset\">>, <<\"US-ASCII\">>},\n                                        {<<\"format\">>, <<\"flowed\">>}\n                                    ],\n                                disposition => <<\"inline\">>,\n                                disposition_params => []\n                            },\n                            <<\"This message contains rich text.\">>},\n                        {<<\"text\">>, <<\"html\">>,\n                            [\n                                {<<\"Content-Type\">>, <<\"text/html;charset=US-ASCII\">>},\n                                {<<\"Content-Transfer-Encoding\">>, <<\"7bit\">>}\n                            ],\n                            #{\n                                content_type_params =>\n                                    [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                                disposition => <<\"inline\">>,\n                                disposition_params => []\n                            },\n                            <<\"<html><body>This message also contains HTML</body></html>\">>}\n                    ]},\n            Result = decode(encode(Email)),\n            ?assertMatch(\n                {<<\"multipart\">>, <<\"alternative\">>, _, _, [\n                    {<<\"text\">>, <<\"plain\">>, _, _, _}, {<<\"text\">>, <<\"html\">>, _, _, _}\n                ]},\n                Result\n            )\n        end},\n        {\"multipart/alternative email with encoding\", fun() ->\n            Email =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>},\n                        {<<\"MIME-Version\">>, <<\"1.0\">>},\n                        {<<\"Content-Type\">>, <<\"multipart/alternative; boundary=wtf-123234234\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"boundary\">>, <<\"wtf-123234234\">>}],\n                        disposition => <<\"inline\">>,\n                        disposition_params => []\n                    },\n                    [\n                        {<<\"text\">>, <<\"plain\">>,\n                            [\n                                {<<\"Content-Type\">>, <<\"text/plain;charset=US-ASCII;format=flowed\">>},\n                                {<<\"Content-Transfer-Encoding\">>, <<\"quoted-printable\">>}\n                            ],\n                            #{\n                                content_type_params =>\n                                    [\n                                        {<<\"charset\">>, <<\"US-ASCII\">>},\n                                        {<<\"format\">>, <<\"flowed\">>}\n                                    ],\n                                disposition => <<\"inline\">>,\n                                disposition_params => []\n                            },\n                            <<\"This message contains rich text.\\r\\n\", \"and is =quoted printable= encoded!\">>},\n                        {<<\"text\">>, <<\"html\">>,\n                            [\n                                {<<\"Content-Type\">>, <<\"text/html;charset=US-ASCII\">>},\n                                {<<\"Content-Transfer-Encoding\">>, <<\"base64\">>}\n                            ],\n                            #{\n                                content_type_params =>\n                                    [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                                disposition => <<\"inline\">>,\n                                disposition_params => []\n                            },\n                            <<\"<html><body>This message also contains\", \"HTML and is base64\",\n                                \"encoded\\r\\n\\r\\n</body></html>\">>}\n                    ]},\n            Result = decode(encode(Email)),\n            ?assertMatch(\n                {<<\"multipart\">>, <<\"alternative\">>, _, _, [\n                    {<<\"text\">>, <<\"plain\">>, _, _,\n                        <<\"This message contains rich text.\\r\\n\", \"and is =quoted printable= encoded!\">>},\n                    {<<\"text\">>, <<\"html\">>, _, _,\n                        <<\"<html><body>This message also contains\", \"HTML and is base64\",\n                            \"encoded\\r\\n\\r\\n</body></html>\">>}\n                ]},\n                Result\n            )\n        end},\n        {\"multipart/mixed email with multipart/alternative does not add an extra empty lines\", fun() ->\n            Email = Getmail(\"message-text-html-attachment.eml\"),\n            Encoded = encode(Email),\n            Re = re:run(Encoded, \"(?:\\\\r\\\\n){3}\", [global, {capture, all, binary}]),\n            ?assertMatch({match, [_]}, Re)\n        end},\n        {\"Missing headers should be added\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result = decode(encode(Email)),\n            ?assertNot(undefined == proplists:get_value(<<\"Message-ID\">>, element(3, Result))),\n            ?assertNot(undefined == proplists:get_value(<<\"Date\">>, element(3, Result))),\n            ?assertEqual(undefined, proplists:get_value(<<\"References\">>, element(3, Result)))\n        end},\n        {\"Reference header should be added in presence of In-Reply-To\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"In-Reply-To\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result = decode(encode(Email)),\n            ?assertEqual(<<\"<abcd@example.com>\">>, proplists:get_value(<<\"References\">>, element(3, Result)))\n        end},\n        {\"Reference header should be appended to in presence of In-Reply-To, if appropriate\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"In-Reply-To\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"References\">>, <<\"<wxyz@example.com>\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result = decode(encode(Email)),\n            ?assertEqual(\n                <<\"<wxyz@example.com> <abcd@example.com>\">>, proplists:get_value(<<\"References\">>, element(3, Result))\n            )\n        end},\n        {\"Reference header should NOT be appended to in presence of In-Reply-To, if already present\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"In-Reply-To\">>, <<\"<abcd@example.com>\">>},\n                        {<<\"References\">>, <<\"<wxyz@example.com> <abcd@example.com>\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{\n                        content_type_params =>\n                            [{<<\"charset\">>, <<\"US-ASCII\">>}],\n                        disposition => <<\"inline\">>\n                    },\n                    <<\"This is a plain message\">>},\n            Result = decode(encode(Email)),\n            ?assertEqual(\n                <<\"<wxyz@example.com> <abcd@example.com>\">>, proplists:get_value(<<\"References\">>, element(3, Result))\n            )\n        end},\n        {\"Content-Transfer-Encoding header should be added if missing and appropriate\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, <<\"This is a plain message with some non-ascii characters øÿ\\r\\nso there\"/utf8>>},\n            Encoded = encode(Email),\n            Result = decode(Encoded),\n            ?assertEqual(\n                <<\"quoted-printable\">>, proplists:get_value(<<\"Content-Transfer-Encoding\">>, element(3, Result))\n            ),\n            Email2 =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, <<\"This is a plain message with no non-ascii characters\">>},\n            Encoded2 = encode(Email2),\n            Result2 = decode(Encoded2),\n            ?assertEqual(undefined, proplists:get_value(<<\"Content-Transfer-Encoding\">>, element(3, Result2))),\n            Email3 =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{transfer_encoding => <<\"base64\">>}, <<\"This is a plain message with no non-ascii characters\">>},\n            Encoded3 = encode(Email3),\n            Result3 = decode(Encoded3),\n            ?assertEqual(<<\"base64\">>, proplists:get_value(<<\"Content-Transfer-Encoding\">>, element(3, Result3)))\n        end},\n        {\"Content-Type header should be added if missing and appropriate\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"html\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, <<\"This is a HTML message with some non-ascii characters øÿ\\r\\nso there\"/utf8>>},\n            Encoded = encode(Email),\n            Result = decode(Encoded),\n            ?assertEqual(\n                <<\"quoted-printable\">>, proplists:get_value(<<\"Content-Transfer-Encoding\">>, element(3, Result))\n            ),\n            ?assertMatch(<<\"text/html;charset=utf-8\">>, proplists:get_value(<<\"Content-Type\">>, element(3, Result))),\n            Email2 =\n                {<<\"text\">>, <<\"html\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, <<\"This is a HTML message with no non-ascii characters\\r\\nso there\">>},\n            Encoded2 = encode(Email2),\n            Result2 = decode(Encoded2),\n            ?assertMatch(\n                <<\"text/html;charset=us-ascii\">>, proplists:get_value(<<\"Content-Type\">>, element(3, Result2))\n            ),\n            Email3 =\n                {<<\"text\">>, <<\"html\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, <<\"This is a text message with some invisible non-ascii characters\\r\\nso there\"/utf8>>},\n            Encoded3 = encode(Email3),\n            Result3 = decode(Encoded3),\n            ?assertMatch(<<\"text/html;charset=utf-8\">>, proplists:get_value(<<\"Content-Type\">>, element(3, Result3)))\n        end},\n        {\"Content-Type header should be added for subparts too, if missing and appropriate\", fun() ->\n            Email4 =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, [\n                        {<<\"text\">>, <<\"plain\">>, [], #{},\n                            <<\"This is a multipart message with some invisible non-ascii characters\\r\\nso there\"/utf8>>}\n                    ]},\n            Encoded4 = encode(Email4),\n            Result4 = decode(Encoded4),\n            ?assertMatch(\n                <<\"text/plain;charset=utf-8\">>,\n                proplists:get_value(<<\"Content-Type\">>, element(3, lists:nth(1, element(5, Result4))))\n            )\n        end},\n        {\"Content-Type header should be not added for subparts if they're text/plain us-ascii\", fun() ->\n            Email4 =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, [\n                        {<<\"text\">>, <<\"plain\">>, [], #{},\n                            <<\"This is a multipart message with no non-ascii characters\\r\\nso there\">>}\n                    ]},\n            Encoded4 = encode(Email4),\n            Result4 = decode(Encoded4),\n            ?assertMatch(\n                undefined, proplists:get_value(<<\"Content-Type\">>, element(3, lists:nth(1, element(5, Result4))))\n            )\n        end},\n        {\"Content-Type header should be added for subparts if they're text/html us-ascii\", fun() ->\n            Email4 =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, [\n                        {<<\"text\">>, <<\"html\">>, [], #{},\n                            <<\"This is a multipart message with no non-ascii characters\\r\\nso there\">>}\n                    ]},\n            Encoded4 = encode(Email4),\n            Result4 = decode(Encoded4),\n            ?assertMatch(\n                <<\"text/html;charset=us-ascii\">>,\n                proplists:get_value(<<\"Content-Type\">>, element(3, lists:nth(1, element(5, Result4))))\n            )\n        end},\n        {\"A boundary should be generated if applicable\", fun() ->\n            Email =\n                {<<\"multipart\">>, <<\"alternative\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"To\">>, <<\"you@example.com\">>},\n                        {<<\"Subject\">>, <<\"This is a test\">>}\n                    ],\n                    #{}, [\n                        {<<\"text\">>, <<\"plain\">>, [], #{},\n                            <<\"This message contains rich text.\\r\\n\", \"and is =quoted printable= encoded!\">>},\n                        {<<\"text\">>, <<\"html\">>, [], #{},\n                            <<\"<html><body>This message also contains\", \"HTML and is base64\",\n                                \"encoded\\r\\n\\r\\n</body></html>\">>}\n                    ]},\n            Encoded = encode(Email),\n            Result = decode(Encoded),\n            Boundary = proplists:get_value(<<\"boundary\">>, maps:get(content_type_params, element(4, Result))),\n            ?assert(is_binary(Boundary)),\n            % ensure we don't add the header multiple times\n            ?assertEqual(1, length(proplists:get_all_values(<<\"Content-Type\">>, element(3, Result)))),\n            % headers should be appended, not prepended\n            ?assertMatch({<<\"From\">>, _}, lists:nth(1, element(3, Result))),\n            ok\n        end}\n    ].\n\nroundtrip_test_() ->\n    [\n        {\"roundtrip test for the gamut\", fun() ->\n            {ok, Email} = file:read_file(\"test/fixtures/the-gamut.eml\"),\n            Decoded = decode(Email),\n            _Encoded = encode(Decoded),\n            %{ok, F1} = file:open(\"f1\", [write]),\n            %{ok, F2} = file:open(\"f2\", [write]),\n            %file:write(F1, Email),\n            %file:write(F2, Encoded),\n            %file:close(F1),\n            %file:close(F2),\n            %?assertEqual(Email, Email),\n            ok\n        end},\n        {\"round trip plain text only email\", fun() ->\n            {ok, Email} = file:read_file(\"test/fixtures/Plain-text-only.eml\"),\n            Decoded = decode(Email),\n            _Encoded = encode(Decoded),\n            %{ok, F1} = file:open(\"f1\", [write]),\n            %{ok, F2} = file:open(\"f2\", [write]),\n            %file:write(F1, Email),\n            %file:write(F2, Encoded),\n            %file:close(F1),\n            %file:close(F2),\n            %?assertEqual(Email, Email),\n            ok\n        end},\n        {\"round trip quoted-printable email\", fun() ->\n            {ok, Email} = file:read_file(\"test/fixtures/testcase1\"),\n            Decoded = decode(Email),\n            _Encoded = encode(Decoded),\n            %{ok, F1} = file:open(\"f1\", [write]),\n            %{ok, F2} = file:open(\"f2\", [write]),\n            %file:write(F1, Email),\n            %file:write(F2, Encoded),\n            %file:close(F1),\n            %file:close(F2),\n            %?assertEqual(Email, Email),\n            ok\n        end}\n    ].\n\ndkim_canonicalization_test_() ->\n    %% * canonicalization from #3.4.5\n    Hdrs = [\n        <<\"A : X\\r\\n\">>,\n        <<\"B : Y\\t\\r\\n\\tZ  \\r\\n\">>\n    ],\n    Body = <<\" C \\r\\nD \\t E\\r\\n\\r\\n\\r\\n\">>,\n    [\n        {\"Simple body canonicalization\", fun() ->\n            ?assertEqual(<<\" C \\r\\nD \\t E\\r\\n\">>, dkim_canonicalize_body(Body, simple)),\n            ?assertEqual(<<\"\\r\\n\">>, dkim_canonicalize_body(<<>>, simple)),\n            ?assertEqual(<<\"\\r\\n\">>, dkim_canonicalize_body(<<\"\\r\\n\\r\\n\\r\\n\">>, simple)),\n            ?assertEqual(<<\"A\\r\\n\\r\\nB\\r\\n\">>, dkim_canonicalize_body(<<\"A\\r\\n\\r\\nB\\r\\n\\r\\n\">>, simple))\n        end},\n        {\"Simple headers canonicalization\", fun() ->\n            ?assertEqual(\n                [\n                    <<\"A : X\\r\\n\">>,\n                    <<\"B : Y\\t\\r\\n\\tZ  \\r\\n\">>\n                ],\n                dkim_canonicalize_headers(Hdrs, simple)\n            )\n        end},\n        {\"Relaxed headers canonicalization\", fun() ->\n            % \\r\\n's are stripped by current impl.\n            ?assertEqual(\n                [\n                    <<\"a:X\">>,\n                    <<\"b:Y Z\">>\n                ],\n                dkim_canonicalize_headers(Hdrs, relaxed)\n            )\n        end}\n    ].\n\ndkim_sign_rsa_test_() ->\n    %% * sign using test/fixtures/dkim*.pem\n    {ok, PrivKey} = file:read_file(\"test/fixtures/dkim-rsa-private.pem\"),\n    [\n        {\"Sign simple\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"Subject\">>, <<\"Hello world!\">>},\n                        {<<\"Date\">>, <<\"Thu, 28 Nov 2013 04:15:44 +0400\">>},\n                        {<<\"Message-ID\">>, <<\"the-id\">>},\n                        {<<\"Content-Type\">>, <<\"text/plain; charset=utf-8\">>}\n                    ],\n                    #{}, <<\"123\">>},\n            Options = [\n                {dkim, [\n                    {s, <<\"foo.bar\">>},\n                    {d, <<\"example.com\">>},\n                    {c, {simple, simple}},\n                    {t, {{2014, 2, 4}, {23, 15, 00}}},\n                    {x, {{2114, 2, 4}, {23, 15, 00}}},\n                    {private_key, {pem_plain, PrivKey}}\n                ]}\n            ],\n\n            Enc = encode(Email, Options),\n            %% This `Enc' value can be verified, for example, by Python script\n            %% https://launchpad.net/dkimpy like:\n            %% >>> pubkey = ''.join(open(\"test/fixtures/dkim-rsa-public.pem\").read().splitlines()[1:-1])\n            %% >>> dns_mock = lambda *args: 'v=DKIM1; g=*; k=rsa; p=' + pubkey\n            %% >>> import dkim\n            %% >>> d = dkim.DKIM(mime_message) % pass `Enc' value as 1'st argument\n            %% >>> d.verify(dnsfunc=dns_mock)\n            %% True\n            {_, _, [{DkimHdrName, DkimHdrVal} | _], _, _} = decode(Enc),\n            ?assertEqual(<<\"DKIM-Signature\">>, DkimHdrName),\n            ?assertEqual(\n                <<\n                    \"t=1391555700; x=4547229300; s=foo.bar; h=from:to:subject:date; d=example.com; c=simple/simple; \"\n                    \"bh=Afm/S7SaxS19en1h955RwsupTF914DQUPqYU8Nh7kpw=; a=rsa-sha256; v=1; \"\n                    \"b=Mtja7WpVvtOFT8rfzOS/2fRZ492jrgsHgD5YUl5zmPQ/NEEMjVhVX0JCkfZxWpxiKe\"\n                    \"qwl7nTJy3xecdg12feGT1rGC+rV0vAX8LVc+AJ4T4A50hE8L4hpJ1Tv5rt2O2t0Xu1Wx\"\n                    \"yH6Cmrhhh56istjL+ba+U1EHhV7uZXGpWXGa4=\"\n                >>,\n                DkimHdrVal\n            )\n        end},\n        {\"Sign relaxed headers, simple body\", fun() ->\n            Email =\n                {<<\"text\">>, <<\"plain\">>,\n                    [\n                        {<<\"From\">>, <<\"me@example.com\">>},\n                        {<<\"Subject\">>, <<\"Hello world!\">>},\n                        {<<\"Date\">>, <<\"Thu, 28 Nov 2013 04:15:44 +0400\">>},\n                        {<<\"Message-ID\">>, <<\"the-id-relaxed\">>},\n                        {<<\"Content-Type\">>, <<\"text/plain; charset=utf-8\">>}\n                    ],\n                    #{}, <<\"123\">>},\n            Options = [\n                {dkim, [\n                    {s, <<\"foo.bar\">>},\n                    {d, <<\"example.com\">>},\n                    {c, {relaxed, simple}},\n                    {private_key, {pem_plain, PrivKey}}\n                ]}\n            ],\n\n            Enc = encode(Email, Options),\n            {_, _, [{DkimHdrName, DkimHdrVal} | _], _, _} = decode(Enc),\n            ?assertEqual(<<\"DKIM-Signature\">>, DkimHdrName),\n            ?assertEqual(\n                <<\n                    \"s=foo.bar; h=from:to:subject:date; d=example.com; c=relaxed/simple; \"\n                    \"bh=Afm/S7SaxS19en1h955RwsupTF914DQUPqYU8Nh7kpw=; a=rsa-sha256; v=1; \"\n                    \"b=dXxKq6A7m4A3AoS90feuLP+IxOyXFTPIibja52E2JCAyOsxvIGlI51xR1LvmEaelv9\"\n                    \"jJTH9iGyAC7RzTKxrWV1QXayvr05bsTy3vDw7P4vfZ1gmspuP/3Icw+J8KEn+p6+CRrf\"\n                    \"T97QadH42PT6XmO2v01q5nhMgNE4yQyf9DBJs=\"\n                >>,\n                DkimHdrVal\n            )\n        end}\n    ].\n\ndkim_sign_ed25519_test_() ->\n    case ed25519_supported() of\n        true ->\n            %% * sign using test/fixtures/dkim*.pem\n            {ok, PrivKey} = file:read_file(\"test/fixtures/dkim-ed25519-private.pem\"),\n            [\n                {\"Sign simple\", fun() ->\n                    Email =\n                        {<<\"text\">>, <<\"plain\">>,\n                            [\n                                {<<\"From\">>, <<\"me@example.com\">>},\n                                {<<\"Subject\">>, <<\"Hello world!\">>},\n                                {<<\"Date\">>, <<\"Thu, 28 Nov 2013 04:15:44 +0400\">>},\n                                {<<\"Message-ID\">>, <<\"the-id\">>},\n                                {<<\"Content-Type\">>, <<\"text/plain; charset=utf-8\">>}\n                            ],\n                            #{}, <<\"123\">>},\n                    Options = [\n                        {dkim, [\n                            {s, <<\"foo.bar\">>},\n                            {d, <<\"example.com\">>},\n                            {c, {simple, simple}},\n                            {a, 'ed25519-sha256'},\n                            {t, {{2014, 2, 4}, {23, 15, 00}}},\n                            {x, {{2114, 2, 4}, {23, 15, 00}}},\n                            {private_key, {pem_plain, PrivKey}}\n                        ]}\n                    ],\n\n                    Enc = encode(Email, Options),\n                    %% This `Enc' value can be verified, for example, by Python script\n                    %% https://launchpad.net/dkimpy like:\n                    %% >>> pubkey = ''.join(open(\"test/fixtures/dkim-ed25519-public.pem\").read().splitlines()[1:-1])\n                    %% >>> dns_mock = lambda *args: 'v=DKIM1; g=*; k=ed25519; p=' + pubkey\n                    %% >>> import dkim\n                    %% >>> d = dkim.DKIM(mime_message) % pass `Enc' value as 1'st argument\n                    %% >>> d.verify(dnsfunc=dns_mock)\n                    %% True\n                    {_, _, [{DkimHdrName, DkimHdrVal} | _], _, _} = decode(Enc),\n                    ?assertEqual(<<\"DKIM-Signature\">>, DkimHdrName),\n                    ?assertEqual(\n                        <<\n                            \"t=1391555700; x=4547229300; s=foo.bar; h=from:to:subject:date; d=example.com; c=simple/simple; \"\n                            \"bh=Afm/S7SaxS19en1h955RwsupTF914DQUPqYU8Nh7kpw=; a=ed25519-sha256; v=1; \"\n                            \"b=bFPndkFlgpFbfVKBF9HiVkQQF/3ojOQT7ycrZYp0yYe4oyItUQexlvd+Q7BviiHv/seLVBESpBjLbthbfb5HDA==\"\n                        >>,\n                        DkimHdrVal\n                    )\n                end},\n                {\"Sign relaxed headers, simple body\", fun() ->\n                    Email =\n                        {<<\"text\">>, <<\"plain\">>,\n                            [\n                                {<<\"From\">>, <<\"me@example.com\">>},\n                                {<<\"Subject\">>, <<\"Hello world!\">>},\n                                {<<\"Date\">>, <<\"Thu, 28 Nov 2013 04:15:44 +0400\">>},\n                                {<<\"Message-ID\">>, <<\"the-id-relaxed\">>},\n                                {<<\"Content-Type\">>, <<\"text/plain; charset=utf-8\">>}\n                            ],\n                            #{}, <<\"123\">>},\n                    Options = [\n                        {dkim, [\n                            {s, <<\"foo.bar\">>},\n                            {d, <<\"example.com\">>},\n                            {c, {relaxed, simple}},\n                            {a, 'ed25519-sha256'},\n                            {private_key, {pem_plain, PrivKey}}\n                        ]}\n                    ],\n\n                    Enc = encode(Email, Options),\n                    {_, _, [{DkimHdrName, DkimHdrVal} | _], _, _} = decode(Enc),\n                    ?assertEqual(<<\"DKIM-Signature\">>, DkimHdrName),\n                    ?assertEqual(\n                        <<\n                            \"s=foo.bar; h=from:to:subject:date; d=example.com; c=relaxed/simple; \"\n                            \"bh=Afm/S7SaxS19en1h955RwsupTF914DQUPqYU8Nh7kpw=; a=ed25519-sha256; v=1; \"\n                            \"b=f7wORU/qmPr4q891m5zmZMadPm9n9e596mBJHBD6tE51PAl4pHdpw9xRC1kwLGmxPTEK5SiQluPVTbDHVhVZBQ==\"\n                        >>,\n                        DkimHdrVal\n                    )\n                end}\n            ];\n        false ->\n            []\n    end.\n\ndkim_sign_ed25519_encrypted_key_test_() ->\n    case ed25519_supported() of\n        true ->\n            %% * sign using test/fixtures/dkim*.pem\n            {ok, EncryptedPrivKey} =\n                file:read_file(\"test/fixtures/dkim-ed25519-encrypted-private.pem\"),\n            [\n                {\"Sign encrypted\", fun() ->\n                    Email =\n                        {<<\"text\">>, <<\"plain\">>,\n                            [\n                                {<<\"From\">>, <<\"me@example.com\">>},\n                                {<<\"Subject\">>, <<\"Hello world!\">>},\n                                {<<\"Date\">>, <<\"Thu, 28 Nov 2013 04:15:44 +0400\">>},\n                                {<<\"Message-ID\">>, <<\"the-id\">>},\n                                {<<\"Content-Type\">>, <<\"text/plain; charset=utf-8\">>}\n                            ],\n                            #{}, <<\"123\">>},\n                    Options = [\n                        {dkim, [\n                            {s, <<\"foo.bar\">>},\n                            {d, <<\"example.com\">>},\n                            {c, {simple, simple}},\n                            {a, 'ed25519-sha256'},\n                            {t, {{2014, 2, 4}, {23, 15, 00}}},\n                            {x, {{2114, 2, 4}, {23, 15, 00}}},\n                            {private_key, {pem_encrypted, EncryptedPrivKey, \"password\"}}\n                        ]}\n                    ],\n\n                    Enc = encode(Email, Options),\n                    %% This `Enc' value can be verified, for example, by Python script\n                    %% https://launchpad.net/dkimpy like:\n                    %% >>> pubkey = ''.join(open(\"test/fixtures/dkim-ed25519-public.pem\").read().splitlines()[1:-1])\n                    %% >>> dns_mock = lambda *args: 'v=DKIM1; g=*; k=ed25519; p=' + pubkey\n                    %% >>> import dkim\n                    %% >>> d = dkim.DKIM(mime_message) % pass `Enc' value as 1'st argument\n                    %% >>> d.verify(dnsfunc=dns_mock)\n                    %% True\n                    {_, _, [{DkimHdrName, DkimHdrVal} | _], _, _} = decode(Enc),\n                    ?assertEqual(<<\"DKIM-Signature\">>, DkimHdrName),\n                    ?assertEqual(\n                        <<\n                            \"t=1391555700; x=4547229300; s=foo.bar; h=from:to:subject:date; d=example.com; c=simple/simple; \"\n                            \"bh=Afm/S7SaxS19en1h955RwsupTF914DQUPqYU8Nh7kpw=; a=ed25519-sha256; v=1; \"\n                            \"b=JgsuW5OmKPk188YRmxs1cLA8mrAf9FNC+s/PYK7Vat7HF4l7FglcoWWHqm0/Cg7o/V+8bP1RNwes1xDKS8/wDQ==\"\n                        >>,\n                        DkimHdrVal\n                    )\n                end}\n            ];\n        false ->\n            []\n    end.\n\n-endif.\n"
  },
  {
    "path": "src/smtp_rfc5322_parse.yrl",
    "content": "%% @doc Parser for [[https://datatracker.ietf.org/doc/html/rfc5322#section-3.4]] \"mailbox-list\" structure\n\nTerminals\n    qstring\n    domain_literal\n    atom\n    '<'\n    '>'\n    ','\n    '@'\n    '.'\n    ':'\n    ';'.\nNonterminals\n    root\n    mailbox_list\n    group\n    mailbox\n    name_addr\n    addr_spec\n    angle_addr\n    display_name\n    word\n    local_part\n    domain\n    dot_atom.\n\nRootsymbol\n    root.\n\nroot ->\n\tmailbox_list : {mailbox_list, '$1'}.\nroot ->\n\tgroup : {group, '$1'}.\n\ngroup ->\n\tdisplay_name ':' ';' : {'$1', []}.\ngroup ->\n\tdisplay_name ':' mailbox_list ';' : {'$1', '$3'}.\n\nmailbox_list ->\n\tmailbox : ['$1'].\nmailbox_list ->\n\tmailbox ',' mailbox_list : ['$1' | '$3'].\n\nmailbox -> name_addr : '$1'.\nmailbox -> addr_spec : {undefined, '$1'}.\n\nname_addr ->\n\tangle_addr : {undefined, '$1'}.\nname_addr ->\n\tdisplay_name angle_addr : {'$1', '$2'}.\n\nangle_addr ->\n\t'<' addr_spec '>' : '$2'.\n\naddr_spec ->\n\tlocal_part '@' domain : {addr, '$1', '$3'}.\n\nlocal_part ->\n\tdot_atom : '$1'.\nlocal_part ->\n\tqstring : value_of('$1').\n\ndisplay_name ->\n\tword : '$1'.\ndisplay_name ->\n\tword display_name : '$1' ++ \" \" ++ '$2'.\n\nword ->\n\tdot_atom : '$1'.\nword ->\n\tqstring : unescape(value_of('$1')).\t% same as local_part, but with unescaping (is it necessary?)\n\ndomain ->\n\tdot_atom : '$1'.\ndomain ->\n\tdomain_literal : value_of('$1').\n\ndot_atom ->\n\tatom : value_of('$1').\ndot_atom ->\n\tatom '.' dot_atom : value_of('$1') ++ \".\" ++ '$3'.\n\nErlang code.\n-ignore_xref([{smtp_rfc5322_parse, return_error, 2}]).\n\n%% Unescaping\nunescape([$\\\\, C | Tail]) ->\n\t%% unescaping\n\t[C | unescape(Tail)];\nunescape([$\" | Tail]) ->\n\t%% stripping quotes (only possible at start and end)\n\tunescape(Tail);\nunescape([C | Tail]) ->\n\t[C | unescape(Tail)];\nunescape([]) -> [].\n\n\nvalue_of(Token) ->\n    try element(3, Token)\n    catch error:badarg ->\n            error({badarg, Token})\n    end.\n"
  },
  {
    "path": "src/smtp_rfc5322_scan.xrl",
    "content": "%% @doc Lexer for [[https://datatracker.ietf.org/doc/html/rfc5322#section-3.4]] \"mailbox-list\" structure\n%% With unicode support from [[https://datatracker.ietf.org/doc/html/rfc6532]].\n%% It's a bit more permissive compared to the one proposed in RFC.\n%% It operates on codepoints! Not bytes! Use `unicode:characters_to_list/1'\n\nDefinitions.\n%% Codepoint ranges which fit in 2/3/4 bytes of UTF-8; rfc3629#section-4\nUTF8_2 = [\\x{80}-\\x{7FF}]\nUTF8_3 = [\\x{800}-\\x{D7FF}\\x{E000}-\\x{FFFD}]\nUTF8_4 = [\\x{10000}-\\x{10FFFF}]\n\nRules.\n\n[\\s\\t]+ : skip_token.\n\n%% rfc5322#section-3.2.5\n%% Anything between double quotes, but double quotes inside should be escaped\n\"([^\\\"]|\\\\\\\")+\" : {token, {qstring, TokenLine, TokenChars}}.\n\n%% rfc5322#section-3.4.1\n%% Anything between brackets, but closing bracket inside should be escaped\n\\[([^\\]]|\\\\\\])+\\] : {token, {domain_literal, TokenLine, TokenChars}}.\n\n%% rfc5322#section-3.2.3\n([0-9a-zA-Z!#\\$\\%&\\'*+\\-/=?^_`\\{|\\}~]|{UTF8_2}|{UTF8_3}|{UTF8_4})+ : {token, {atom, TokenLine, TokenChars}}.\n\n\\< : {token, {'<', TokenLine}}.\n\\> : {token, {'>', TokenLine}}.\n\\, : {token, {',', TokenLine}}.\n@ : {token, {'@', TokenLine}}.\n\\. : {token, {'.', TokenLine}}.\n% mailbox group\n\\: : {token, {':', TokenLine}}.\n\\; : {token, {';', TokenLine}}.\n\nErlang code.\n"
  },
  {
    "path": "src/smtp_rfc822_parse.yrl",
    "content": "Nonterminals\n  addresses\n  address\n  name\n  names\n  email.\n\nTerminals\n  string\n  ',' '<' '>'.\n  \nRootsymbol\n  addresses.\n\nEndsymbol\n  '$end'.\n\naddresses -> address : ['$1'].\naddresses -> address ',' addresses : ['$1' | '$3'].\naddresses -> '$empty' : [].\n\naddress -> email : {undefined, '$1'}.\naddress -> '<' email '>' : {undefined, '$2'}.\naddress -> names '<' email '>' : {lists:flatten('$1'), '$3'}.\n\nemail -> string : element(3, '$1').\n\nnames -> name : '$1'.\nnames -> name names : ['$1', \" \" | '$2'].\nname -> string : element(3, '$1').\n"
  },
  {
    "path": "src/smtp_server_example.erl",
    "content": "%% @doc A simple example callback module for `gen_smtp_server_session' that also serves as\n%% documentation for the required callback API.\n\n-module(smtp_server_example).\n-behaviour(gen_smtp_server_session).\n\n-export([\n    init/4,\n    handle_HELO/2,\n    handle_EHLO/3,\n    handle_MAIL/2,\n    handle_MAIL_extension/2,\n    handle_RCPT/2,\n    handle_RCPT_extension/2,\n    handle_DATA/4,\n    handle_RSET/1,\n    handle_VRFY/2,\n    handle_other/3,\n    handle_AUTH/4,\n    handle_STARTTLS/1,\n    handle_info/2,\n    handle_error/3,\n    code_change/3,\n    terminate/2\n]).\n-include_lib(\"kernel/include/logger.hrl\").\n-define(LOGGER_META, #{domain => [gen_smtp, example_handler]}).\n-define(RELAY, true).\n\n-record(state, {\n    options = [] :: list()\n}).\n\n-type error_message() :: {'error', string(), #state{}}.\n\n%% @doc Initialize the callback module's state for a new session.\n%% The arguments to the function are the SMTP server's hostname (for use in the SMTP banner),\n%% The number of current sessions (eg. so you can do session limiting), the IP address of the\n%% connecting client, and a freeform list of options for the module. The Options are extracted\n%% from the `callbackoptions' parameter passed into the `gen_smtp_server_session' when it was\n%% started.\n%%\n%% If you want to continue the session, return `{ok, Banner, State}' where Banner is the SMTP\n%% banner to send to the client and State is the callback module's state. The State will be passed\n%% to ALL subsequent calls to the callback module, so it can be used to keep track of the SMTP\n%% session. You can also return `{stop, Reason, Message}' where the session will exit with Reason\n%% and send Message to the client.\n-spec init(\n    Hostname :: inet:hostname(),\n    SessionCount :: non_neg_integer(),\n    Address :: inet:ip_address(),\n    Options :: list()\n) -> {'ok', iodata(), #state{}} | {'stop', any(), iodata()}.\ninit(Hostname, SessionCount, Address, Options) ->\n    ?LOG_INFO(\"peer: ~p\", [Address], ?LOGGER_META),\n    case SessionCount > 20 of\n        false ->\n            Banner = [Hostname, \" ESMTP smtp_server_example\"],\n            State = #state{options = Options},\n            {ok, Banner, State};\n        true ->\n            ?LOG_WARNING(\"Connection limit exceeded\", ?LOGGER_META),\n            {stop, normal, [\"421 \", Hostname, \" is too busy to accept mail right now\"]}\n    end.\n\n%% @doc Handle the HELO verb from the client. Arguments are the Hostname sent by the client as\n%% part of the HELO and the callback State.\n%%\n%% Return values are `{ok, State}' to simply continue with a new state, `{ok, MessageSize, State}'\n%% to continue with the SMTP session but to impose a maximum message size (which you can determine\n%% , for example, by looking at the IP address passed in to the init function) and the new callback\n%% state. You can reject the HELO by returning `{error, Message, State}' and the Message will be\n%% sent back to the client. The reject message MUST contain the SMTP status code, eg. 554.\n-spec handle_HELO(Hostname :: binary(), State :: #state{}) ->\n    {'ok', pos_integer(), #state{}} | {'ok', #state{}} | error_message().\nhandle_HELO(<<\"invalid\">>, State) ->\n    % contrived example\n    {error, \"554 invalid hostname\", State};\nhandle_HELO(<<\"trusted_host\">>, State) ->\n    %% no size limit because we trust them.\n    {ok, State};\nhandle_HELO(Hostname, State) ->\n    ?LOG_INFO(\"HELO from ~s\", [Hostname], ?LOGGER_META),\n    % 640kb of HELO should be enough for anyone.\n    MaxSize = proplists:get_value(size, State#state.options, 655360),\n    {ok, MaxSize, State}.\n%If {ok, State} was returned here, we'd use the default 10mb limit\n\n%% @doc Handle the EHLO verb from the client. As with EHLO the hostname is provided as an argument,\n%% but in addition to that the list of ESMTP Extensions enabled in the session is passed. This list\n%% of extensions can be modified by the callback module to add/remove extensions.\n%%\n%% The return values are `{ok, Extensions, State}' where Extensions is the new list of extensions\n%% to use for this session or `{error, Message, State}' where Message is the reject message as\n%% with handle_HELO.\n-spec handle_EHLO(Hostname :: binary(), Extensions :: list(), State :: #state{}) ->\n    {'ok', list(), #state{}} | error_message().\nhandle_EHLO(<<\"invalid\">>, _Extensions, State) ->\n    % contrived example\n    {error, \"554 invalid hostname\", State};\nhandle_EHLO(Hostname, Extensions, State) ->\n    ?LOG_INFO(\"EHLO from ~s\", [Hostname], ?LOGGER_META),\n    % You can advertise additional extensions, or remove some defaults\n    MyExtensions1 =\n        case proplists:get_value(auth, State#state.options, false) of\n            true ->\n                % auth is enabled, so advertise it\n                Extensions ++ [{\"AUTH\", \"PLAIN LOGIN CRAM-MD5\"}, {\"STARTTLS\", true}];\n            false ->\n                Extensions\n        end,\n    MyExtensions2 =\n        case proplists:get_value(size, State#state.options) of\n            undefined ->\n                MyExtensions1;\n            infinity ->\n                [{\"SIZE\", \"0\"} | lists:keydelete(\"SIZE\", 1, MyExtensions1)];\n            Size when is_integer(Size), Size > 0 ->\n                [{\"SIZE\", integer_to_list(Size)} | lists:keydelete(\"SIZE\", 1, MyExtensions1)]\n        end,\n    {ok, MyExtensions2, State}.\n\n%% @doc Handle the MAIL FROM verb. The From argument is the email address specified by the\n%% MAIL FROM command. Extensions to the MAIL verb are handled by the `handle_MAIL_extension'\n%% function.\n%%\n%% Return values are either `{ok, State}' or `{error, Message, State}' as before.\n-spec handle_MAIL(From :: binary(), State :: #state{}) -> {'ok', #state{}} | error_message().\nhandle_MAIL(<<\"badguy@blacklist.com\">>, State) ->\n    {error, \"552 go away\", State};\nhandle_MAIL(From, State) ->\n    ?LOG_INFO(\"Mail from ~s\", [From], ?LOGGER_META),\n    % you can accept or reject the FROM address here\n    {ok, State}.\n\n%% @doc Handle an extension to the MAIL verb. Return either `{ok, State}' or `error' to reject\n%% the option.\n-spec handle_MAIL_extension(Extension :: binary(), State :: #state{}) -> {'ok', #state{}} | 'error'.\nhandle_MAIL_extension(<<\"X-SomeExtension\">> = Extension, State) ->\n    ?LOG_INFO(\"Mail from extension ~s\", [Extension], ?LOGGER_META),\n    % any MAIL extensions can be handled here\n    {ok, State};\nhandle_MAIL_extension(Extension, _State) ->\n    ?LOG_WARNING(\"Unknown MAIL FROM extension ~s\", [Extension], ?LOGGER_META),\n    error.\n\n-spec handle_RCPT(To :: binary(), State :: #state{}) ->\n    {'ok', #state{}} | {'error', string(), #state{}}.\nhandle_RCPT(<<\"nobody@example.com\">>, State) ->\n    {error, \"550 No such recipient\", State};\nhandle_RCPT(To, State) ->\n    ?LOG_INFO(\"Mail to ~s\", [To], ?LOGGER_META),\n    % you can accept or reject RCPT TO addresses here, one per call\n    {ok, State}.\n\n-spec handle_RCPT_extension(Extension :: binary(), State :: #state{}) -> {'ok', #state{}} | 'error'.\nhandle_RCPT_extension(<<\"X-SomeExtension\">> = Extension, State) ->\n    % any RCPT TO extensions can be handled here\n    ?LOG_INFO(\"Mail to extension ~s\", [Extension], ?LOGGER_META),\n    {ok, State};\nhandle_RCPT_extension(Extension, _State) ->\n    ?LOG_WARNING(\"Unknown RCPT TO extension ~s\", [Extension], ?LOGGER_META),\n    error.\n\n%% @doc Handle the DATA verb from the client, which corresponds to the body of\n%% the message. After receiving the body, a SMTP server can put the email in\n%% a queue for later delivering while a LMTP server can handle the delivery\n%% directly (LMTP servers are supposed to be simpler and handle emails to\n%% local users directly without the need for a queue). Relaying the email to\n%% another server is also an option.\n%%\n%% When using the SMTP protocol, `handle_DATA' should return a single \"aggregate\" delivery status\n%% in the form of a `{ok, SuccessMsg, State}' tuple or `{error, ErrorMsg, State}'.\n%% At this point, if `ok' is returned, we have accepted the full responsibility\n%% of delivering the email.\n%%\n%% When using the LMTP protocol, `handle_DATA' should return a status for\n%% each accepted address in `handle_RCPT' in the form of a `{multiple, StatusList, State}' tuple\n%% where `StatusList' is a list of `{ok, SuccessMsg}' or `{error, ErrorMsg}' tuples\n%% (the statuses should be presented in the same order as the recipient addresses were accepted).\n%% For each `ok' in the `StatusList', we have accepted full responsibility for\n%% delivering the email to that specific recipient. When a single recipient is\n%% specified the returned value can also follow the SMTP format.\n%%\n%% `ErrorMsg' should always start with the SMTP error code, while `SuccessMsg'\n%% should not (the `250' code is automatically prepended).\n%%\n%% According to the SMTP specification the, responsibility of delivering an\n%% email must be taken seriously and the servers MUST NOT loose the message.\n-spec handle_DATA(\n    From :: binary(),\n    To :: [binary(), ...],\n    Data :: binary(),\n    State :: #state{}\n) ->\n    {ok | error, string(), #state{}}\n    | {multiple, [{ok | error, string()}], #state{}}.\nhandle_DATA(_From, _To, <<>>, State) ->\n    {error, \"552 Message too small\", State};\nhandle_DATA(From, To, Data, State) ->\n    % if RELAY is true, then relay email to email address, else send email data to console\n    case proplists:get_value(relay, State#state.options, false) of\n        true ->\n            relay(From, To, Data);\n        false ->\n            % some kind of unique id\n            Reference = lists:flatten([\n                io_lib:format(\"~2.16.0b\", [X])\n             || <<X>> <= erlang:md5(term_to_binary(unique_id()))\n            ]),\n            case proplists:get_value(parse, State#state.options, false) of\n                false ->\n                    ok;\n                true ->\n                    % In this example we try to decode the email\n                    try mimemail:decode(Data) of\n                        _Result ->\n                            ?LOG_INFO(\"Message decoded successfully!\", ?LOGGER_META)\n                    catch\n                        What:Why ->\n                            ?LOG_WARNING(\"Message decode FAILED with ~p:~p\", [What, Why], ?LOGGER_META),\n                            case proplists:get_value(dump, State#state.options, false) of\n                                false ->\n                                    ok;\n                                true ->\n                                    %% optionally dump the failed email somewhere for analysis\n                                    File = \"dump/\" ++ Reference,\n                                    case filelib:ensure_dir(File) of\n                                        ok ->\n                                            file:write_file(File, Data);\n                                        _ ->\n                                            ok\n                                    end\n                            end\n                    end\n            end,\n            queue_or_deliver(From, To, Data, Reference, State)\n    end.\n\n-spec handle_RSET(State :: #state{}) -> #state{}.\nhandle_RSET(State) ->\n    % reset any relevant internal state\n    State.\n\n-spec handle_VRFY(Address :: binary(), State :: #state{}) ->\n    {'ok', string(), #state{}} | {'error', string(), #state{}}.\nhandle_VRFY(<<\"someuser\">>, State) ->\n    {ok, \"someuser@\" ++ smtp_util:guess_FQDN(), State};\nhandle_VRFY(_Address, State) ->\n    {error, \"252 VRFY disabled by policy, just send some mail\", State}.\n\n-spec handle_other(Verb :: binary(), Args :: binary(), #state{}) -> {string(), #state{}}.\nhandle_other(Verb, _Args, State) ->\n    % You can implement other SMTP verbs here, if you need to\n    {[\"500 Error: command not recognized : '\", Verb, \"'\"], State}.\n\n%% this callback is OPTIONAL\n%% it only gets called if you add AUTH to your ESMTP extensions\n-spec handle_AUTH(\n    Type :: 'login' | 'plain' | 'cram-md5',\n    Username :: binary(),\n    Password :: binary() | {binary(), binary()},\n    #state{}\n) -> {'ok', #state{}} | 'error'.\nhandle_AUTH(Type, <<\"username\">>, <<\"PaSSw0rd\">>, State) when Type =:= login; Type =:= plain ->\n    {ok, State};\nhandle_AUTH('cram-md5', <<\"username\">>, {Digest, Seed}, State) ->\n    case smtp_util:compute_cram_digest(<<\"PaSSw0rd\">>, Seed) of\n        Digest ->\n            {ok, State};\n        _ ->\n            error\n    end;\nhandle_AUTH(_Type, _Username, _Password, _State) ->\n    error.\n\n%% this callback is OPTIONAL\n%% it only gets called if you add STARTTLS to your ESMTP extensions\n-spec handle_STARTTLS(#state{}) -> #state{}.\nhandle_STARTTLS(State) ->\n    ?LOG_INFO(\"TLS Started\", ?LOGGER_META),\n    State.\n\n-spec handle_info(Info :: term(), State :: term()) ->\n    {noreply, NewState :: term()}\n    | {noreply, NewState :: term(), timeout() | hibernate}\n    | {stop, Reason :: term(), NewState :: term()}.\nhandle_info(_Info, State) ->\n    ?LOG_INFO(\"handle_info(~p, ~p)\", [_Info, State], ?LOGGER_META),\n    {noreply, State}.\n\n%% This optional callback is called when different kinds of protocol errors happen.\n%% Return {ok, State} to let gen_smtp decide how to act or {stop, Reason, #state{}}\n%% to stop the process with reason Reason immediately.\n-spec handle_error(gen_smtp_server_session:error_class(), any(), #state{}) ->\n    {ok, #state{}} | {stop, any(), #state{}}.\nhandle_error(Class, Details, State) ->\n    ?LOG_INFO(\"handle_error(~p, ~p, ~p)\", [Class, Details, State], ?LOGGER_META),\n    {ok, State}.\n\n-spec code_change(OldVsn :: any(), State :: #state{}, Extra :: any()) -> {ok, #state{}}.\ncode_change(_OldVsn, State, _Extra) ->\n    {ok, State}.\n\n-spec terminate(Reason :: any(), State :: #state{}) -> {'ok', any(), #state{}}.\nterminate(Reason, State) ->\n    {ok, Reason, State}.\n\n%%% Internal Functions %%%\n\nunique_id() ->\n    erlang:unique_integer().\n\n-spec relay(binary(), [binary()], binary()) -> ok.\nrelay(_, [], _) ->\n    ok;\nrelay(From, [To | Rest], Data) ->\n    % relay message to email address\n    [_User, Host] = string:tokens(binary_to_list(To), \"@\"),\n    gen_smtp_client:send({From, [To], erlang:binary_to_list(Data)}, [{relay, Host}]),\n    relay(From, Rest, Data).\n\n%% @doc Helps `handle_DATA' to deal with the received email.\n%% This function is not directly required by the behaviour.\n-spec queue_or_deliver(\n    From :: binary(),\n    To :: [binary(), ...],\n    Data :: binary(),\n    Reference :: string(),\n    State :: #state{}\n) ->\n    {ok | error, string(), #state{}}\n    | {multiple, [{ok | error, string()}], #state{}}.\nqueue_or_deliver(From, To, Data, Reference, State) ->\n    % At this point, if we return ok, we've accepted responsibility for the emaill\n    Length = byte_size(Data),\n    case proplists:get_value(protocol, State#state.options, smtp) of\n        smtp ->\n            ?LOG_INFO(\n                \"message from ~s to ~p queued as ~s, body length ~p\",\n                [\n                    From, To, Reference, Length\n                ],\n                ?LOGGER_META\n            ),\n            % ... should actually handle the email,\n            %     if `ok` is returned we are taking the responsibility of the delivery.\n            {ok, [\"queued as \", Reference], State};\n        lmtp ->\n            ?LOG_INFO(\"message from ~s delivered to ~p, body length ~p\", [From, To, Length], ?LOGGER_META),\n            Multiple = [{ok, [\"delivered to \", Recipient]} || Recipient <- To],\n            % ... should actually handle the email for each recipient for each `ok`\n            {multiple, Multiple, State}\n    end.\n"
  },
  {
    "path": "src/smtp_socket.erl",
    "content": "%%% Copyright 2009 Jack Danger Canty <code@jackcanty.com>. All rights reserved.\n%%%\n%%% Permission is hereby granted, free of charge, to any person obtaining\n%%% a copy of this software and associated documentation files (the\n%%% \"Software\"), to deal in the Software without restriction, including\n%%% without limitation the rights to use, copy, modify, merge, publish,\n%%% distribute, sublicense, and/or sell copies of the Software, and to\n%%% permit persons to whom the Software is furnished to do so, subject to\n%%% the following conditions:\n%%%\n%%% The above copyright notice and this permission notice shall be\n%%% included in all copies or substantial portions of the Software.\n%%%\n%%% THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n%%% LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n%%% OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n%%% WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n%% @doc Facilitates transparent gen_tcp/ssl socket handling\n-module(smtp_socket).\n\n-define(TCP_LISTEN_OPTIONS, [\n    {active, false},\n    {backlog, 30},\n    {ip, {0, 0, 0, 0}},\n    {keepalive, true},\n    {packet, line},\n    {reuseaddr, true}\n]).\n-define(TCP_CONNECT_OPTIONS, [\n    {active, false},\n    {packet, line},\n    {ip, {0, 0, 0, 0}},\n    {port, 0}\n]).\n-define(SSL_LISTEN_OPTIONS, [\n    {active, false},\n    {backlog, 30},\n    {certfile, \"server.crt\"},\n    {depth, 0},\n    {keepalive, true},\n    {keyfile, \"server.key\"},\n    {packet, line},\n    {reuse_sessions, false},\n    {reuseaddr, true}\n]).\n-define(SSL_CONNECT_OPTIONS, [\n    {active, false},\n    {depth, 0},\n    {packet, line},\n    {ip, {0, 0, 0, 0}},\n    {port, 0}\n]).\n\n-ifdef(TEST).\n-include_lib(\"eunit/include/eunit.hrl\").\n-endif.\n\n%% API\n-export([connect/3, connect/4, connect/5]).\n-export([listen/2, listen/3, accept/1, accept/2]).\n-export([send/2, recv/2, recv/3]).\n-export([controlling_process/2]).\n-export([peername/1]).\n-export([close/1, shutdown/2]).\n-export([active_once/1]).\n-export([setopts/2]).\n-export([get_proto/1]).\n-export([begin_inet_async/1]).\n-export([handle_inet_async/1, handle_inet_async/2, handle_inet_async/3]).\n-export([extract_port_from_socket/1]).\n-export([to_ssl_server/1, to_ssl_server/2, to_ssl_server/3]).\n-export([to_ssl_client/1, to_ssl_client/2, to_ssl_client/3]).\n-export([type/1]).\n\n-type protocol() :: 'tcp' | 'ssl'.\n-type address() :: inet:ip_address() | string() | binary().\n-type socket() :: ssl:sslsocket() | gen_tcp:socket().\n\n-export_type([socket/0]).\n\n%%%-----------------------------------------------------------------\n%%% API\n%%%-----------------------------------------------------------------\n-spec connect(Protocol :: protocol(), Address :: address(), Port :: pos_integer()) ->\n    {ok, socket()} | {error, any()}.\nconnect(Protocol, Address, Port) ->\n    connect(Protocol, Address, Port, [], infinity).\n\n-spec connect(\n    Protocol :: protocol(), Address :: address(), Port :: pos_integer(), Options :: list()\n) -> {ok, socket()} | {error, any()}.\nconnect(Protocol, Address, Port, Opts) ->\n    connect(Protocol, Address, Port, Opts, infinity).\n\n-spec connect(\n    Protocol :: protocol(),\n    Address :: address(),\n    Port :: pos_integer(),\n    Options :: list(),\n    Time :: non_neg_integer() | 'infinity'\n) -> {ok, socket()} | {error, any()}.\nconnect(tcp, Address, Port, Opts, Time) ->\n    gen_tcp:connect(Address, Port, tcp_connect_options(Opts), Time);\nconnect(ssl, Address, Port, Opts, Time) ->\n    ssl:connect(Address, Port, ssl_connect_options(Opts), Time).\n\n-spec listen(Protocol :: protocol(), Port :: pos_integer()) -> {ok, socket()} | {error, any()}.\nlisten(Protocol, Port) ->\n    listen(Protocol, Port, []).\n\n-spec listen(Protocol :: protocol(), Port :: pos_integer(), Options :: list()) ->\n    {ok, socket()} | {error, any()}.\nlisten(ssl, Port, Options) ->\n    ssl:listen(Port, ssl_listen_options(Options));\nlisten(tcp, Port, Options) ->\n    gen_tcp:listen(Port, tcp_listen_options(Options)).\n\n-spec accept(Socket :: socket()) -> {'ok', socket()} | {'error', any()}.\naccept(Socket) ->\n    accept(Socket, infinity).\n\n-spec accept(Socket :: socket(), Timeout :: pos_integer() | 'infinity') ->\n    {'ok', socket()} | {'error', any()}.\naccept(Socket, Timeout) when is_port(Socket) ->\n    case gen_tcp:accept(Socket, Timeout) of\n        {ok, NewSocket} ->\n            {ok, Opts} = inet:getopts(Socket, [active, keepalive, packet, reuseaddr]),\n            inet:setopts(NewSocket, Opts),\n            {ok, NewSocket};\n        {error, _} = Error ->\n            Error\n    end;\naccept(Socket, Timeout) ->\n    case ssl:transport_accept(Socket, Timeout) of\n        {ok, NewSocket} ->\n            ssl:handshake(NewSocket);\n        {error, _} = Error ->\n            Error\n    end.\n\n-spec send(Socket :: socket(), Data :: binary() | string() | iolist()) -> 'ok' | {'error', any()}.\nsend(Socket, Data) when is_port(Socket) ->\n    gen_tcp:send(Socket, Data);\nsend(Socket, Data) ->\n    ssl:send(Socket, Data).\n\n-spec recv(Socket :: socket(), Length :: non_neg_integer()) -> {'ok', any()} | {'error', any()}.\nrecv(Socket, Length) ->\n    recv(Socket, Length, infinity).\n\n-spec recv(\n    Socket :: socket(), Length :: non_neg_integer(), Timeout :: non_neg_integer() | 'infinity'\n) -> {'ok', any()} | {'error', any()}.\nrecv(Socket, Length, Timeout) when is_port(Socket) ->\n    gen_tcp:recv(Socket, Length, Timeout);\nrecv(Socket, Length, Timeout) ->\n    ssl:recv(Socket, Length, Timeout).\n\n-spec controlling_process(Socket :: socket(), NewOwner :: pid()) -> 'ok' | {'error', any()}.\ncontrolling_process(Socket, NewOwner) when is_port(Socket) ->\n    gen_tcp:controlling_process(Socket, NewOwner);\ncontrolling_process(Socket, NewOwner) ->\n    ssl:controlling_process(Socket, NewOwner).\n\n-spec peername(Socket :: socket()) ->\n    {ok, {inet:ip_address(), non_neg_integer()}} | {'error', any()}.\npeername(Socket) when is_port(Socket) ->\n    inet:peername(Socket);\npeername(Socket) ->\n    ssl:peername(Socket).\n\n-spec close(Socket :: socket()) -> 'ok'.\nclose(Socket) when is_port(Socket) ->\n    gen_tcp:close(Socket);\nclose(Socket) ->\n    ssl:close(Socket).\n\n-spec shutdown(Socket :: socket(), How :: 'read' | 'write' | 'read_write') ->\n    'ok' | {'error', any()}.\nshutdown(Socket, How) when is_port(Socket) ->\n    gen_tcp:shutdown(Socket, How);\nshutdown(Socket, How) ->\n    ssl:shutdown(Socket, How).\n\n-spec active_once(Socket :: socket()) -> 'ok' | {'error', any()}.\nactive_once(Socket) when is_port(Socket) ->\n    inet:setopts(Socket, [{active, once}]);\nactive_once(Socket) ->\n    ssl:setopts(Socket, [{active, once}]).\n\n-spec setopts(Socket :: socket(), Options :: list()) -> 'ok' | {'error', any()}.\nsetopts(Socket, Options) when is_port(Socket) ->\n    inet:setopts(Socket, Options);\nsetopts(Socket, Options) ->\n    ssl:setopts(Socket, Options).\n\n-spec get_proto(Socket :: any()) -> 'tcp' | 'ssl'.\nget_proto(Socket) when is_port(Socket) ->\n    tcp;\nget_proto(_Socket) ->\n    ssl.\n\n%% @doc {inet_async,...} will be sent to current process when a client connects\n-spec begin_inet_async(Socket :: socket()) -> any().\nbegin_inet_async(Socket) when is_port(Socket) ->\n    prim_inet:async_accept(Socket, -1);\nbegin_inet_async(Socket) ->\n    Port = extract_port_from_socket(Socket),\n    begin_inet_async(Port).\n\n%% @doc handle the {inet_async,...} message\n-spec handle_inet_async(Message :: {'inet_async', socket(), any(), {'ok', socket()}}) ->\n    {'ok', socket()}.\nhandle_inet_async({inet_async, ListenSocket, _, {ok, ClientSocket}}) ->\n    handle_inet_async(ListenSocket, ClientSocket, []).\n\n-spec handle_inet_async(ListenSocket :: socket(), ClientSocket :: socket()) -> {'ok', socket()}.\nhandle_inet_async(ListenObject, ClientSocket) ->\n    handle_inet_async(ListenObject, ClientSocket, []).\n\n-spec handle_inet_async(ListenSocket :: socket(), ClientSocket :: socket(), Options :: list()) ->\n    {'ok', socket()}.\nhandle_inet_async(ListenObject, ClientSocket, Options) ->\n    ListenSocket = extract_port_from_socket(ListenObject),\n    case set_sockopt(ListenSocket, ClientSocket) of\n        ok -> ok;\n        Error -> erlang:error(set_sockopt, Error)\n    end,\n    %% Signal the network driver that we are ready to accept another connection\n    begin_inet_async(ListenSocket),\n    %% If the listening socket is SSL then negotiate the client socket\n    case is_port(ListenObject) of\n        true ->\n            {ok, ClientSocket};\n        false ->\n            {ok, UpgradedClientSocket} = to_ssl_server(ClientSocket, Options),\n            {ok, UpgradedClientSocket}\n    end.\n\n%% @doc Upgrade a TCP connection to SSL\n-spec to_ssl_server(Socket :: socket()) -> {'ok', ssl:sslsocket()} | {'error', any()}.\nto_ssl_server(Socket) ->\n    to_ssl_server(Socket, []).\n\n-spec to_ssl_server(Socket :: socket(), Options :: list()) ->\n    {'ok', ssl:sslsocket()} | {'error', any()}.\nto_ssl_server(Socket, Options) ->\n    to_ssl_server(Socket, Options, infinity).\n\n-spec to_ssl_server(\n    Socket :: socket(), Options :: list(), Timeout :: non_neg_integer() | 'infinity'\n) -> {'ok', ssl:sslsocket()} | {'error', any()}.\nto_ssl_server(Socket, Options, Timeout) when is_port(Socket) ->\n    ssl:handshake(Socket, ssl_listen_options(Options), Timeout);\nto_ssl_server(_Socket, _Options, _Timeout) ->\n    {error, already_ssl}.\n\n-spec to_ssl_client(Socket :: socket()) -> {'ok', ssl:sslsocket()} | {'error', 'already_ssl'}.\nto_ssl_client(Socket) ->\n    to_ssl_client(Socket, []).\n\n-spec to_ssl_client(Socket :: socket(), Options :: list()) ->\n    {'ok', ssl:sslsocket()} | {'error', 'already_ssl'}.\nto_ssl_client(Socket, Options) ->\n    to_ssl_client(Socket, Options, infinity).\n\n-spec to_ssl_client(\n    Socket :: socket(), Options :: list(), Timeout :: non_neg_integer() | 'infinity'\n) -> {'ok', ssl:sslsocket()} | {'error', 'already_ssl'}.\nto_ssl_client(Socket, Options, Timeout) when is_port(Socket) ->\n    ssl:connect(Socket, ssl_connect_options(Options), Timeout);\nto_ssl_client(_Socket, _Options, _Timeout) ->\n    {error, already_ssl}.\n\n-spec type(Socket :: socket()) -> protocol().\ntype(Socket) when is_port(Socket) ->\n    tcp;\ntype(_Socket) ->\n    ssl.\n\n%%%-----------------------------------------------------------------\n%%% Internal functions (OS_Mon configuration)\n%%%-----------------------------------------------------------------\n\ntcp_listen_options([Format | Options]) when Format =:= list; Format =:= binary ->\n    tcp_listen_options(Options, Format);\ntcp_listen_options(Options) ->\n    tcp_listen_options(Options, list).\ntcp_listen_options(Options, Format) ->\n    parse_address([Format | proplist_merge(Options, ?TCP_LISTEN_OPTIONS)]).\n\nssl_listen_options([Format | Options]) when Format =:= list; Format =:= binary ->\n    ssl_listen_options(Options, Format);\nssl_listen_options(Options) ->\n    ssl_listen_options(Options, list).\nssl_listen_options(Options, Format) ->\n    parse_address([Format | proplist_merge(Options, ?SSL_LISTEN_OPTIONS)]).\n\ntcp_connect_options([Format | Options]) when Format =:= list; Format =:= binary ->\n    tcp_connect_options(Options, Format);\ntcp_connect_options(Options) ->\n    tcp_connect_options(Options, list).\ntcp_connect_options(Options, Format) ->\n    parse_address([Format | proplist_merge(Options, ?TCP_CONNECT_OPTIONS)]).\n\nssl_connect_options([Format | Options]) when Format =:= list; Format =:= binary ->\n    ssl_connect_options(Options, Format);\nssl_connect_options(Options) ->\n    ssl_connect_options(Options, list).\nssl_connect_options(Options, Format) ->\n    parse_address([Format | proplist_merge(Options, ?SSL_CONNECT_OPTIONS)]).\n\nproplist_merge(PrimaryList, DefaultList) ->\n    {PrimaryTuples, PrimaryOther} = lists:partition(fun(X) -> is_tuple(X) end, PrimaryList),\n    {DefaultTuples, DefaultOther} = lists:partition(fun(X) -> is_tuple(X) end, DefaultList),\n    MergedTuples = lists:ukeymerge(\n        1,\n        lists:keysort(1, PrimaryTuples),\n        lists:keysort(1, DefaultTuples)\n    ),\n    MergedOther = lists:umerge(lists:sort(PrimaryOther), lists:sort(DefaultOther)),\n    MergedTuples ++ MergedOther.\n\nparse_address(Options) ->\n    case proplists:get_value(ip, Options) of\n        X when is_tuple(X) ->\n            Options;\n        X when is_list(X) ->\n            case inet_parse:address(X) of\n                {error, _} = Error ->\n                    erlang:error(Error);\n                {ok, IP} ->\n                    proplists:delete(ip, Options) ++ [{ip, IP}]\n            end;\n        _ ->\n            Options\n    end.\n\n-spec extract_port_from_socket(Socket :: socket()) -> port().\nextract_port_from_socket({sslsocket, _, {SSLPort, _}}) ->\n    SSLPort;\nextract_port_from_socket(Socket) ->\n    Socket.\n\n-spec set_sockopt(ListSock :: port(), CliSocket :: port()) -> 'ok' | any().\nset_sockopt(ListenObject, ClientSocket) ->\n    ListenSocket = extract_port_from_socket(ListenObject),\n    true = inet_db:register_socket(ClientSocket, inet_tcp),\n    case prim_inet:getopts(ListenSocket, [active, nodelay, keepalive, delay_send, priority, tos]) of\n        {ok, Opts} ->\n            case prim_inet:setopts(ClientSocket, Opts) of\n                ok ->\n                    ok;\n                Error ->\n                    smtp_socket:close(ClientSocket),\n                    Error\n            end;\n        Error ->\n            smtp_socket:close(ClientSocket),\n            Error\n    end.\n\n-ifdef(TEST).\n-define(TEST_PORT, 7586).\n\nconnect_test_() ->\n    [\n        {\"listen and connect via tcp\", fun() ->\n            Self = self(),\n            Port = ?TEST_PORT + 1,\n            Ref = make_ref(),\n            spawn(fun() ->\n                {ok, ListenSocket} = listen(tcp, Port),\n                ?assert(is_port(ListenSocket)),\n                Self ! {Ref, listen},\n                {ok, ServerSocket} = accept(ListenSocket),\n                controlling_process(ServerSocket, Self),\n                Self ! {Ref, ListenSocket}\n            end),\n            receive\n                {Ref, listen} -> ok\n            end,\n            {ok, ClientSocket} = connect(tcp, \"localhost\", Port),\n            receive\n                {Ref, ListenSocket} when is_port(ListenSocket) -> ok\n            end,\n            ?assert(is_port(ClientSocket)),\n            close(ListenSocket)\n        end},\n        {\"listen and connect via ssl\", fun() ->\n            Self = self(),\n            Port = ?TEST_PORT + 2,\n            Ref = make_ref(),\n            application:ensure_all_started(gen_smtp),\n            spawn(fun() ->\n                {ok, ListenSocket} = listen(ssl, Port, [\n                    {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                    {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                ]),\n                ?assertMatch([sslsocket | _], tuple_to_list(ListenSocket)),\n                Self ! {Ref, listen},\n                {ok, ServerSocket} = accept(ListenSocket),\n                controlling_process(ServerSocket, Self),\n                Self ! {Ref, ListenSocket}\n            end),\n            receive\n                {Ref, listen} -> ok\n            end,\n            {ok, ClientSocket} = connect(ssl, \"localhost\", Port, []),\n            receive\n                {Ref, {sslsocket, _, _} = ListenSocket} -> ok\n            end,\n            ?assertMatch([sslsocket | _], tuple_to_list(ClientSocket)),\n            close(ListenSocket)\n        end}\n    ].\n\nevented_connections_test_() ->\n    [\n        {\"current process receives connection to TCP listen sockets\", fun() ->\n            Port = ?TEST_PORT + 3,\n            {ok, ListenSocket} = listen(tcp, Port),\n            begin_inet_async(ListenSocket),\n            spawn(fun() -> connect(tcp, \"localhost\", Port) end),\n            receive\n                {inet_async, ListenSocket, _, {ok, ServerSocket}} -> ok\n            end,\n            {ok, NewServerSocket} = handle_inet_async(ListenSocket, ServerSocket),\n            ?assert(is_port(ServerSocket)),\n            %% only true for TCP\n            ?assertEqual(ServerSocket, NewServerSocket),\n            ?assert(is_port(ListenSocket)),\n            % Stop the async\n            spawn(fun() -> connect(tcp, \"localhost\", Port) end),\n            receive\n                _Ignored -> ok\n            end,\n            close(NewServerSocket),\n            close(ListenSocket)\n        end},\n        {\"current process receives connection to SSL listen sockets\", fun() ->\n            Port = ?TEST_PORT + 4,\n            application:ensure_all_started(gen_smtp),\n            {ok, ListenSocket} = listen(ssl, Port, [\n                {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n            ]),\n            begin_inet_async(ListenSocket),\n            spawn(fun() -> connect(ssl, \"localhost\", Port) end),\n            receive\n                {inet_async, _ListenPort, _, {ok, ServerSocket}} -> ok\n            end,\n            {ok, NewServerSocket} = handle_inet_async(ListenSocket, ServerSocket, [\n                {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n            ]),\n            ?assert(is_port(ServerSocket)),\n            ?assertMatch([sslsocket | _], tuple_to_list(NewServerSocket)),\n            ?assertMatch([sslsocket | _], tuple_to_list(ListenSocket)),\n            %Stop the async\n            spawn(fun() -> connect(ssl, \"localhost\", Port) end),\n            receive\n                _Ignored -> ok\n            end,\n            close(ListenSocket),\n            close(NewServerSocket),\n            ok\n        end},\n        %% TODO: figure out if the following passes because\n        %% of an incomplete test case or if this really is\n        %% a magical feature where a single listener\n        %% can respond to either ssl or tcp connections.\n        {\"current TCP listener receives SSL connection\", fun() ->\n            Port = ?TEST_PORT + 5,\n            application:ensure_all_started(gen_smtp),\n            {ok, ListenSocket} = listen(tcp, Port),\n            begin_inet_async(ListenSocket),\n            spawn(fun() -> connect(ssl, \"localhost\", Port) end),\n            ServerSocket =\n                receive\n                    {inet_async, _ListenPort, _, {ok, ServerSocket0}} -> ServerSocket0\n                end,\n            ?assertMatch({ok, ServerSocket}, handle_inet_async(ListenSocket, ServerSocket)),\n            ?assert(is_port(ListenSocket)),\n            ?assert(is_port(ServerSocket)),\n            {ok, NewServerSocket} = to_ssl_server(ServerSocket, [\n                {certfile, \"test/fixtures/mx1.example.com-server.crt\"},\n                {keyfile, \"test/fixtures/mx1.example.com-server.key\"}\n            ]),\n            ?assertMatch([sslsocket | _], tuple_to_list(NewServerSocket)),\n            % Stop the async\n            spawn(fun() -> connect(ssl, \"localhost\", Port) end),\n            receive\n                _Ignored -> ok\n            end,\n            close(ListenSocket),\n            close(NewServerSocket)\n        end}\n    ].\n\naccept_test_() ->\n    [\n        {\"Accept via tcp\", fun() ->\n            Port = ?TEST_PORT + 6,\n            {ok, ListenSocket} = listen(tcp, Port, tcp_listen_options([])),\n            ?assert(is_port(ListenSocket)),\n            spawn(fun() -> connect(ssl, \"localhost\", Port, tcp_connect_options([])) end),\n            {ok, ServerSocket} = accept(ListenSocket),\n            ?assert(is_port(ListenSocket)),\n            close(ServerSocket),\n            close(ListenSocket)\n        end},\n        {\"Accept via ssl\", fun() ->\n            Port = ?TEST_PORT + 7,\n            application:ensure_all_started(gen_smtp),\n            {ok, ListenSocket} = listen(ssl, Port, [\n                {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n            ]),\n            ?assertMatch([sslsocket | _], tuple_to_list(ListenSocket)),\n            spawn(fun() -> connect(ssl, \"localhost\", Port) end),\n            accept(ListenSocket),\n            close(ListenSocket)\n        end}\n    ].\n\ntype_test_() ->\n    [\n        {\"a tcp socket returns 'tcp'\", fun() ->\n            {ok, ListenSocket} = listen(tcp, ?TEST_PORT + 8),\n            ?assertMatch(tcp, type(ListenSocket)),\n            close(ListenSocket)\n        end},\n        {\"an ssl socket returns 'ssl'\", fun() ->\n            application:ensure_all_started(gen_smtp),\n            {ok, ListenSocket} = listen(ssl, ?TEST_PORT + 9, [\n                {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n            ]),\n            ?assertMatch(ssl, type(ListenSocket)),\n            close(ListenSocket)\n        end}\n    ].\n\nactive_once_test_() ->\n    [\n        {\"socket is set to active:once on tcp\", fun() ->\n            {ok, ListenSocket} = listen(tcp, ?TEST_PORT + 10, tcp_listen_options([])),\n            ?assertEqual({ok, [{active, false}]}, inet:getopts(ListenSocket, [active])),\n            active_once(ListenSocket),\n            ?assertEqual({ok, [{active, once}]}, inet:getopts(ListenSocket, [active])),\n            close(ListenSocket)\n        end},\n        {\"socket is set to active:once on ssl\", fun() ->\n            {ok, ListenSocket} = listen(\n                ssl,\n                ?TEST_PORT + 11,\n                ssl_listen_options([\n                    {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                    {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                ])\n            ),\n            ?assertEqual({ok, [{active, false}]}, ssl:getopts(ListenSocket, [active])),\n            active_once(ListenSocket),\n            ?assertEqual({ok, [{active, once}]}, ssl:getopts(ListenSocket, [active])),\n            close(ListenSocket)\n        end}\n    ].\n\noption_test_() ->\n    [\n        {\"tcp_listen_options has defaults\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?TCP_LISTEN_OPTIONS]), lists:sort(tcp_listen_options([]))\n            )\n        end},\n        {\"tcp_connect_options has defaults\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?TCP_CONNECT_OPTIONS]), lists:sort(tcp_connect_options([]))\n            )\n        end},\n        {\"ssl_listen_options has defaults\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?SSL_LISTEN_OPTIONS]), lists:sort(ssl_listen_options([]))\n            )\n        end},\n        {\"ssl_connect_options has defaults\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?SSL_CONNECT_OPTIONS]), lists:sort(ssl_connect_options([]))\n            )\n        end},\n        {\"tcp_listen_options defaults to list type\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?TCP_LISTEN_OPTIONS]),\n                lists:sort(tcp_listen_options([{active, false}]))\n            ),\n            ?assertEqual(\n                lists:sort([binary | ?TCP_LISTEN_OPTIONS]),\n                lists:sort(tcp_listen_options([binary, {active, false}]))\n            )\n        end},\n        {\"tcp_connect_options defaults to list type\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?TCP_CONNECT_OPTIONS]),\n                lists:sort(tcp_connect_options([{active, false}]))\n            ),\n            ?assertEqual(\n                lists:sort([binary | ?TCP_CONNECT_OPTIONS]),\n                lists:sort(tcp_connect_options([binary, {active, false}]))\n            )\n        end},\n        {\"ssl_listen_options defaults to list type\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?SSL_LISTEN_OPTIONS]),\n                lists:sort(ssl_listen_options([{active, false}]))\n            ),\n            ?assertEqual(\n                lists:sort([binary | ?SSL_LISTEN_OPTIONS]),\n                lists:sort(ssl_listen_options([binary, {active, false}]))\n            )\n        end},\n        {\"ssl_connect_options defaults to list type\", fun() ->\n            ?assertEqual(\n                lists:sort([list | ?SSL_CONNECT_OPTIONS]),\n                lists:sort(ssl_connect_options([{active, false}]))\n            ),\n            ?assertEqual(\n                lists:sort([binary | ?SSL_CONNECT_OPTIONS]),\n                lists:sort(ssl_connect_options([binary, {active, false}]))\n            )\n        end},\n        {\"tcp_listen_options merges provided proplist\", fun() ->\n            ?assertEqual(\n                [\n                    list\n                    | lists:keysort(1, [\n                        {active, true},\n                        {backlog, 30},\n                        {ip, {0, 0, 0, 0}},\n                        {keepalive, true},\n                        {packet, 2},\n                        {reuseaddr, true}\n                    ])\n                ],\n                tcp_listen_options([{active, true}, {packet, 2}])\n            )\n        end},\n        {\"tcp_connect_options merges provided proplist\", fun() ->\n            ?assertEqual(\n                lists:sort([\n                    list,\n                    {active, true},\n                    {packet, 2},\n                    {ip, {0, 0, 0, 0}},\n                    {port, 0}\n                ]),\n                lists:sort(tcp_connect_options([{active, true}, {packet, 2}]))\n            )\n        end},\n        {\"ssl_listen_options merges provided proplist\", fun() ->\n            ?assertEqual(\n                [\n                    list\n                    | lists:keysort(1, [\n                        {active, true},\n                        {backlog, 30},\n                        {certfile, \"server.crt\"},\n                        {depth, 0},\n                        {keepalive, true},\n                        {keyfile, \"server.key\"},\n                        {packet, 2},\n                        {reuse_sessions, false},\n                        {reuseaddr, true}\n                    ])\n                ],\n                ssl_listen_options([{active, true}, {packet, 2}])\n            ),\n            ?assertEqual(\n                [\n                    list\n                    | lists:keysort(1, [\n                        {active, false},\n                        {backlog, 30},\n                        {certfile, \"../server.crt\"},\n                        {depth, 0},\n                        {keepalive, true},\n                        {keyfile, \"../server.key\"},\n                        {packet, line},\n                        {reuse_sessions, false},\n                        {reuseaddr, true}\n                    ])\n                ],\n                ssl_listen_options([{certfile, \"../server.crt\"}, {keyfile, \"../server.key\"}])\n            )\n        end},\n        {\"ssl_connect_options merges provided proplist\", fun() ->\n            ?assertEqual(\n                lists:sort([\n                    list,\n                    {active, true},\n                    {depth, 0},\n                    {ip, {0, 0, 0, 0}},\n                    {port, 0},\n                    {packet, 2}\n                ]),\n                lists:sort(ssl_connect_options([{active, true}, {packet, 2}]))\n            )\n        end}\n    ].\n\nssl_upgrade_test_() ->\n    [\n        {\"TCP connection can be upgraded to ssl\", fun() ->\n            Self = self(),\n            Port = ?TEST_PORT + 12,\n            application:ensure_all_started(gen_smtp),\n            spawn(fun() ->\n                {ok, ListenSocket} = listen(tcp, Port),\n                Self ! listening,\n                {ok, ServerSocket} = accept(ListenSocket),\n                {ok, NewServerSocket} = smtp_socket:to_ssl_server(\n                    ServerSocket,\n                    [\n                        {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                        {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                    ]\n                ),\n                Self ! {sock, NewServerSocket}\n            end),\n            receive\n                listening -> ok\n            end,\n            erlang:yield(),\n            {ok, ClientSocket} = connect(tcp, \"localhost\", Port),\n            ?assert(is_port(ClientSocket)),\n            {ok, NewClientSocket} = to_ssl_client(ClientSocket),\n            ?assertMatch([sslsocket | _], tuple_to_list(NewClientSocket)),\n            receive\n                {sock, NewServerSocket} -> ok\n            end,\n            ?assertMatch({sslsocket, _, _}, NewServerSocket),\n            close(NewClientSocket),\n            close(NewServerSocket)\n        end},\n        {\"SSL server connection can't be upgraded again\", fun() ->\n            Self = self(),\n            Port = ?TEST_PORT + 13,\n            application:ensure_all_started(gen_smtp),\n            spawn(fun() ->\n                {ok, ListenSocket} = listen(ssl, Port, [\n                    {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                    {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                ]),\n                Self ! listening,\n                {ok, ServerSocket} = accept(ListenSocket),\n                ?assertMatch({error, already_ssl}, to_ssl_server(ServerSocket)),\n                close(ServerSocket)\n            end),\n            receive\n                listening -> ok\n            end,\n            erlang:yield(),\n            {ok, ClientSocket} = connect(ssl, \"localhost\", Port),\n            close(ClientSocket)\n        end},\n        {\"SSL client connection can't be upgraded again\", fun() ->\n            Self = self(),\n            Port = ?TEST_PORT + 14,\n            application:ensure_all_started(gen_smtp),\n            spawn(fun() ->\n                {ok, ListenSocket} = listen(ssl, Port, [\n                    {keyfile, \"test/fixtures/mx1.example.com-server.key\"},\n                    {certfile, \"test/fixtures/mx1.example.com-server.crt\"}\n                ]),\n                Self ! listening,\n                {ok, ServerSocket} = accept(ListenSocket),\n                Self ! {sock, ServerSocket}\n            end),\n            receive\n                listening -> ok\n            end,\n            erlang:yield(),\n            {ok, ClientSocket} = connect(ssl, \"localhost\", Port),\n            receive\n                {sock, ServerSocket} -> ok\n            end,\n            ?assertMatch({error, already_ssl}, to_ssl_client(ClientSocket)),\n            close(ClientSocket),\n            close(ServerSocket)\n        end}\n    ].\n-endif.\n"
  },
  {
    "path": "src/smtp_util.erl",
    "content": "%%% Copyright 2009 Andrew Thompson <andrew@hijacked.us>. All rights reserved.\n%%%\n%%% Redistribution and use in source and binary forms, with or without\n%%% modification, are permitted provided that the following conditions are met:\n%%%\n%%%   1. Redistributions of source code must retain the above copyright notice,\n%%%      this list of conditions and the following disclaimer.\n%%%   2. Redistributions in binary form must reproduce the above copyright\n%%%      notice, this list of conditions and the following disclaimer in the\n%%%      documentation and/or other materials provided with the distribution.\n%%%\n%%% THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR\n%%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n%%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n%%% EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n%%% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n%%% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n%%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n%%% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n%%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n%%% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n%% @doc Module with some general utility functions for SMTP.\n\n-module(smtp_util).\n-export([\n    mxlookup/1,\n    guess_FQDN/0,\n    compute_cram_digest/2,\n    get_cram_string/1,\n    trim_crlf/1,\n    rfc5322_timestamp/0,\n    zone/0,\n    generate_message_id/0,\n    parse_rfc822_addresses/1,\n    parse_rfc5322_addresses/1,\n    combine_rfc822_addresses/1,\n    generate_message_boundary/0\n]).\n\n-include_lib(\"kernel/include/inet.hrl\").\n\n-type name_address() :: {Name :: string() | undefined, Address :: string()}.\n\n% Use parse_rfc5322_addresses/1 instead\n-deprecated([{parse_rfc822_addresses, 1}]).\n\n%% @doc returns a sorted list of mx servers for `Domain', lowest distance first\nmxlookup(Domain) ->\n    case whereis(inet_db) of\n        P when is_pid(P) ->\n            ok;\n        _ ->\n            inet_db:start()\n    end,\n    case lists:keyfind(nameserver, 1, inet_db:get_rc()) of\n        false ->\n            % we got no nameservers configured, suck in resolv.conf\n            inet_config:do_load_resolv(os:type(), longnames);\n        _ ->\n            ok\n    end,\n    case inet_res:lookup(Domain, in, mx) of\n        [] ->\n            lists:map(fun(X) -> {10, inet_parse:ntoa(X)} end, inet_res:lookup(Domain, in, a));\n        Result ->\n            lists:sort(Result)\n    end.\n\n%% @doc guess the current host's fully qualified domain name, on error return \"localhost\"\n-spec guess_FQDN() -> string().\nguess_FQDN() ->\n    {ok, Hostname} = inet:gethostname(),\n    guess_FQDN_1(Hostname, inet:gethostbyname(Hostname)).\n\nguess_FQDN_1(_Hostname, {ok, #hostent{h_name = FQDN}}) ->\n    FQDN;\nguess_FQDN_1(Hostname, {error, nxdomain = Error}) ->\n    error_logger:info_msg(\n        \"~p could not get FQDN for ~p (error ~p), using \\\"localhost\\\" instead.\",\n        [?MODULE, Error, Hostname]\n    ),\n    \"localhost\".\n\n%% @doc Compute the CRAM digest of `Key' and `Data'\n-spec compute_cram_digest(Key :: binary(), Data :: binary()) -> binary().\ncompute_cram_digest(Key, Data) ->\n    Bin = hmac_md5(Key, Data),\n    list_to_binary([io_lib:format(\"~2.16.0b\", [X]) || <<X>> <= Bin]).\n\n-if(?OTP_RELEASE >= 23).\nhmac_md5(Key, Data) ->\n    crypto:mac(hmac, md5, Key, Data).\n-else.\nhmac_md5(Key, Data) ->\n    crypto:hmac(md5, Key, Data).\n-endif.\n\n%% @doc Generate a seed string for CRAM.\n-spec get_cram_string(Hostname :: string()) -> string().\nget_cram_string(Hostname) ->\n    binary_to_list(\n        base64:encode(\n            lists:flatten(\n                io_lib:format(\"<~B.~B@~s>\", [\n                    rand:uniform(4294967295), rand:uniform(4294967295), Hostname\n                ])\n            )\n        )\n    ).\n\n%% @doc Trim \\r\\n from `String'\n-spec trim_crlf(String :: string()) -> string().\ntrim_crlf(String) ->\n    string:strip(string:strip(String, right, $\\n), right, $\\r).\n\n-define(DAYS, [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"]).\n-define(MONTHS, [\n    \"Jan\",\n    \"Feb\",\n    \"Mar\",\n    \"Apr\",\n    \"May\",\n    \"Jun\",\n    \"Jul\",\n    \"Aug\",\n    \"Sep\",\n    \"Oct\",\n    \"Nov\",\n    \"Dec\"\n]).\n%% @doc Generate a RFC 5322 timestamp based on the current time\nrfc5322_timestamp() ->\n    {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),\n    NDay = calendar:day_of_the_week(Year, Month, Day),\n    DoW = lists:nth(NDay, ?DAYS),\n    MoY = lists:nth(Month, ?MONTHS),\n    io_lib:format(\"~s, ~b ~s ~b ~2..0b:~2..0b:~2..0b ~s\", [\n        DoW, Day, MoY, Year, Hour, Minute, Second, zone()\n    ]).\n\n%% @doc Calculate the current timezone and format it like -0400. Borrowed from YAWS.\nzone() ->\n    Time = erlang:universaltime(),\n    LocalTime = calendar:universal_time_to_local_time(Time),\n    DiffSecs =\n        calendar:datetime_to_gregorian_seconds(LocalTime) -\n            calendar:datetime_to_gregorian_seconds(Time),\n    zone((DiffSecs / 3600) * 100).\n\n%% Ugly reformatting code to get times like +0000 and -1300\n\nzone(Val) when Val < 0 ->\n    io_lib:format(\"-~4..0w\", [trunc(abs(Val))]);\nzone(Val) when Val >= 0 ->\n    io_lib:format(\"+~4..0w\", [trunc(abs(Val))]).\n\n%% @doc Generate a unique message ID\ngenerate_message_id() ->\n    FQDN = guess_FQDN(),\n    Md5 = [\n        io_lib:format(\"~2.16.0b\", [X])\n     || <<X>> <= erlang:md5(term_to_binary([unique_id(), FQDN]))\n    ],\n    io_lib:format(\"<~s@~s>\", [Md5, FQDN]).\n\n%% @doc Generate a unique MIME message boundary\ngenerate_message_boundary() ->\n    FQDN = guess_FQDN(),\n    [\n        \"_=\",\n        [\n            io_lib:format(\"~2.36.0b\", [X])\n         || <<X>> <= erlang:md5(term_to_binary([unique_id(), FQDN]))\n        ],\n        \"=_\"\n    ].\n\nunique_id() ->\n    {erlang:system_time(), erlang:unique_integer()}.\n\n-define(is_whitespace(Ch), (Ch =< 32)).\n\ncombine_rfc822_addresses([]) ->\n    <<>>;\ncombine_rfc822_addresses(Addresses) ->\n    iolist_to_binary(combine_rfc822_addresses(Addresses, [])).\n\ncombine_rfc822_addresses([], [32, $, | Acc]) ->\n    lists:reverse(Acc);\ncombine_rfc822_addresses([{undefined, Email} | Rest], Acc) ->\n    combine_rfc822_addresses(Rest, [32, $,, Email | Acc]);\ncombine_rfc822_addresses([{\"\", Email} | Rest], Acc) ->\n    combine_rfc822_addresses(Rest, [32, $,, Email | Acc]);\ncombine_rfc822_addresses([{<<>>, Email} | Rest], Acc) ->\n    combine_rfc822_addresses(Rest, [32, $,, Email | Acc]);\ncombine_rfc822_addresses([{Name, Email} | Rest], Acc) ->\n    Quoted = [opt_quoted(Name), \" <\", Email, \">\"],\n    combine_rfc822_addresses(Rest, [32, $,, Quoted | Acc]).\n\nopt_quoted(B) when is_binary(B) ->\n    opt_quoted(binary_to_list(B));\nopt_quoted(S) when is_list(S) ->\n    NoControls = lists:map(\n        fun\n            (C) when C < 32 -> 32;\n            (C) -> C\n        end,\n        S\n    ),\n    case lists:any(fun is_special/1, NoControls) of\n        false ->\n            NoControls;\n        true ->\n            lists:flatten([\n                $\",\n                lists:map(\n                    fun\n                        ($\\\") -> [$\\\\, $\\\"];\n                        ($\\\\) -> [$\\\\, $\\\\];\n                        (C) -> C\n                    end,\n                    NoControls\n                ),\n                $\"\n            ])\n    end.\n\n% See https://www.w3.org/Protocols/rfc822/3_Lexical.html#z2\nis_special($() -> true;\nis_special($)) -> true;\nis_special($<) -> true;\nis_special($>) -> true;\nis_special($@) -> true;\nis_special($,) -> true;\nis_special($;) -> true;\nis_special($:) -> true;\nis_special($\\\\) -> true;\nis_special($\\\") -> true;\nis_special($.) -> true;\nis_special($[) -> true;\nis_special($]) -> true;\n% special for some smtp servers\nis_special($') -> true;\nis_special(_) -> false.\n\n%% @doc Parse list of mail addresses in RFC-5322#section-3.4 `mailbox-list' format\n-spec parse_rfc5322_addresses(string() | binary()) -> {ok, [name_address()]} | {error, any()}.\nparse_rfc5322_addresses(B) when is_binary(B) ->\n    parse_rfc5322_addresses(unicode:characters_to_list(B));\nparse_rfc5322_addresses(S) when is_list(S) ->\n    case smtp_rfc5322_scan:string(S) of\n        {ok, Tokens, _L} ->\n            F = fun({Name, {addr, Local, Domain}}) ->\n                {Name, Local ++ \"@\" ++ Domain}\n            end,\n            case smtp_rfc5322_parse:parse(Tokens) of\n                {ok, {mailbox_list, AddrList}} ->\n                    {ok, lists:map(F, AddrList)};\n                {ok, {group, {_Groupame, AddrList}}} ->\n                    {ok, lists:map(F, AddrList)};\n                {error, _} = Err ->\n                    Err\n            end;\n        {error, Reason, _L} ->\n            {error, Reason}\n    end.\n\n-spec parse_rfc822_addresses(string() | binary()) -> {ok, [name_address()]} | {error, any()}.\nparse_rfc822_addresses(B) when is_binary(B) ->\n    parse_rfc822_addresses(unicode:characters_to_list(B));\nparse_rfc822_addresses(S) when is_list(S) ->\n    Scanned = lists:reverse([{'$end', 0} | scan_rfc822(S, [])]),\n    smtp_rfc822_parse:parse(Scanned).\n\nscan_rfc822([], Acc) ->\n    Acc;\nscan_rfc822([Ch | R], Acc) when ?is_whitespace(Ch) ->\n    scan_rfc822(R, Acc);\nscan_rfc822([$\" | R], Acc) ->\n    {Token, Rest} = scan_rfc822_scan_endquote(R, [], false),\n    scan_rfc822(Rest, [{string, 0, Token} | Acc]);\nscan_rfc822([$, | Rest], Acc) ->\n    scan_rfc822(Rest, [{',', 0} | Acc]);\nscan_rfc822([$< | Rest], Acc) ->\n    {Token, R} = scan_rfc822_scan_endpointybracket(Rest),\n    scan_rfc822(R, [{'>', 0}, {string, 0, Token}, {'<', 0} | Acc]);\nscan_rfc822(String, Acc) ->\n    %% Capture everything except \"SP < > ,\"\n    case re:run(String, \"^([^\\s<>,]+)(.*)\", [{capture, all_but_first, list}]) of\n        {match, [Token, Rest]} ->\n            scan_rfc822(Rest, [{string, 0, Token} | Acc]);\n        nomatch ->\n            [{string, 0, String} | Acc]\n    end.\n\nscan_rfc822_scan_endpointybracket(String) ->\n    case re:run(String, \"(.*?)>(.*)\", [{capture, all_but_first, list}]) of\n        {match, [Token, Rest]} ->\n            {Token, Rest};\n        nomatch ->\n            {String, []}\n    end.\n\nscan_rfc822_scan_endquote([$\\\\ | R], Acc, InEscape) ->\n    %% in escape\n    scan_rfc822_scan_endquote(R, Acc, not (InEscape));\nscan_rfc822_scan_endquote([$\" | R], Acc, true) ->\n    scan_rfc822_scan_endquote(R, [$\" | Acc], false);\nscan_rfc822_scan_endquote([$\" | Rest], Acc, false) ->\n    %% Done!\n    {lists:reverse(Acc), Rest};\nscan_rfc822_scan_endquote([Ch | Rest], Acc, _) ->\n    scan_rfc822_scan_endquote(Rest, [Ch | Acc], false).\n"
  },
  {
    "path": "test/fixtures/Plain-text-only-no-MIME.eml",
    "content": "Message-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n"
  },
  {
    "path": "test/fixtures/Plain-text-only-no-content-type.eml",
    "content": "Message-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n"
  },
  {
    "path": "test/fixtures/Plain-text-only-with-boundary-header.eml",
    "content": "Message-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798g\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text, but has an incorrect content type\r\nspecifiying a boundary.\r\n"
  },
  {
    "path": "test/fixtures/Plain-text-only.eml",
    "content": "Message-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n"
  },
  {
    "path": "test/fixtures/chinesemail",
    "content": "Return-Path: <reiyg3@ae9.com>\r\nX-Original-To: andrew@hijacked.us\r\nDelivered-To: andrew@hijacked.us\r\nReceived: from ae9.com (unknown [219.129.89.33])\r\n\tby hijacked.us (Postfix) with ESMTP id 53DB6B3FC\r\n\tfor <andrew@hijacked.us>; Thu,  9 Apr 2009 16:37:24 -0400 (EDT)\r\nFrom: =?GB2312?B?xvM=?= <reiyg3@ae9.com>\r\nSubject: =?GB2312?B?xvMg0rUgssMg1LEgt+cgz9UgueYgsdwwNDozNzoyMQ==?=\r\nTo: andrew@hijacked.us\r\nContent-Type: text/plain;charset=\"GB2312\"\r\nDate: Fri, 10 Apr 2009 04:37:23 +0800\r\nX-Priority: 3\r\nX-Mailer: Foxmail 4.1 [cn]\r\nMessage-Id: <20090409203724.53DB6B3FC@hijacked.us>\r\n\r\n               ҵԱչܼHRƶȡԱֲ׫д\r\n\r\n        ʱ    :2009418-19\t       \r\n        ʱ    :2009425-26\t       \r\n        ʱ    :2009523-24        \r\n        ʱ    :2009530-31         \r\n\r\n            : 020- \r\n                  0755- \r\n                  021-  \r\n                  010- \r\n\r\n   -    ã 2000 /ˣ-Ρϡͣ\r\n\r\n --֤-飺 м600 / ߼800/(μ֤ԵѧԱ)\r\n\r\n ע\r\n        1. μ֤ѧ-ԱѵμӿԺϸ<<ְҵ֤׼ϻ>>䷢<<    Դ-ʦ>>ʹӢİ˫ְҵʸ֤飬ʹ֤ȫͨУϿɣٷ      ϲѯ\r\n        2μ֤ѧԱύ֤뼰һƬ\r\n        3-̽15ڽ֤ݼĸѧԱ\r\n        4֤й˲ⱸ\r\n\r\n --\r\n\r\n     ȫںХͣиҵ׷׵ڵнԱ͡ \r\nǣڵнԱ͵ǳϸ񣬲˵λ޴ľ⳥븺Ӱ죬Ӧ\r\nڵڵнԱͶͶ飬˵λİʸߴ90%ЧڵнԱͣѳΪHRʿҵ߲Եʹ\r\n\r\n     ⡶Ͷͬ涨ҵƶ޸йعƶʱӦְȫְۣ빤ְ\r\nƽЭȷ90%ϵҵûʶһҪԣ߸β ƶ򲻺ϷƶȽΪһֽ\r\n     һƵĹƶȣԹΪַͶߵĺϷȨ棬ҿЧԤͶ귨ɿӡ-©\r\n\r\n --ʦ--ܣ\r\n\r\nʦ,ҹͶԱϵ-רңͶٲԱ߼ʦѵϯʣ: Ͷ\r\nҵЭ; Դ-ЭᡢͶѧ20ʦʦ2004꿪ʼȫѲͶ\r\nͶͬؿ-̣ҵ10000ңʵѧͶ߷ʵʹ-УѧԱ\r\nۡ-ȤǳѧԱѸѧáܹҵ-ߡԴҵߵĺڶѧԱ\r\nʾһʵáЧʵͶ-̣\r\n    ʦ굣ҵɹʣרŴͶϼͶоҵ-еͶù\r\n˽⣬Ͷװ1000ˡҵ漰㽭աϺ㶫\r\nɽĴ졢ϡϡϡϡȵأԸͶطн˽⣬Ͷк\r\nоͷḻʵս飬ȺڡԴϷбרҵ־ý巢Ͷϵ20ࡣͻΪ\r\nְ¼ܶýɷãڹ۵أȺ21CNȸ紫ýתء\r\n    \r\n\r\n ---Ҫ\r\n \r\n\r\n \t1. нҵȨ\r\n \t2. ʲôµнڲϷ\r\n \t3. ǿнݼ١ͣнְںϷ\r\n \t4. нȻŸλı仯仯\r\n \t5. ΥнڵķռȷʽЩ\r\n \t6. ͨͶͬԼܵڡнķɷգ\r\n\t7. ϷͶͬЩǷЩ\r\n\t8. λǷͶ֧ͬ2òΣ\r\n\t9. α˲žԴԱķգ\r\n\t10.Դ˲ţԱ֪ͨ\r\n\t11.ͶͬЧ˵λЩףã\r\n\t12.Ͷͷְ־ܽ汨棬ʲôգ\r\n\t13.Ͷҵʱְ֯˵λܷʹ\r\n\t14.˵λⲻͶ߰ŹͶߡż١Ϸ\r\n\t15.ʲô£˵λԽ͡ڡŮְ\r\n\t16.ҵⶨͶͬǷҪͶֱǷӰ䷨Ч\r\n\t17.Уѧҵ򹤣˫ǷͶϵ\r\n\t18.ﵽͶǩͶͬǷͶĵ\r\n\t19.˾ҵ߲ǩͶͬ»ỹϼܲţ\r\n\t20.Ͷְ2ٴְģҵܷԼڣ\r\n\t21.Լ¼ķΧԱ֤ڼԱûκηգ\r\n\t22.ԼΥƶȵķΧԱ֤Աûκηգ\r\n\t23.ԼشʧķΧԱ֤˹ʧԱûκηգ\r\n\t24.ԡΥ͡Ͷߣ·Ҫ֧òΪʲô\r\n\t25.ҵƵġòԼΥԼ𡱸Լ\r\n\r\n\t\r\n\r\n ۺϡӡ䰸\r\n\r\n 1ڴԱ\r\n 2ò\r\n 3ʡӰѰ\r\n 4ʵ참̷ʵսɵ\r\n\r\n                     . 66cc_88cc@163.com\r\n"
  },
  {
    "path": "test/fixtures/dkim-ed25519-encrypted-private.pem",
    "content": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIGKME4GCSqGSIb3DQEFDTBBMCkGCSqGSIb3DQEFDDAcBAjWxBqVOoAQmQICCAAw\nDAYIKoZIhvcNAgkFADAUBggqhkiG9w0DBwQINxHTI3T4bPEEOFrkHOCl0Y4wOEPa\nTEMzq2vB5tqpSVcbbup6BdRGV1f7yDsk+9l9f08m3pZUIbeNgUy1Y9JmUjxU\n-----END ENCRYPTED PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/dkim-ed25519-encrypted-public.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAHWHDpSxS5ABadBDrOKcpyaImlzV4//pJ3A3UgdLuFMk=\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "test/fixtures/dkim-ed25519-private.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEINLp5tYtDtUVSeH4BJb3+ygipAjPHFm4eB0QNWlhcUNZ\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/dkim-ed25519-public.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAgxFnePs7aR/rt5KBGSaJU4T+Uh2cIvLtV6cBz5ypIYE=\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "test/fixtures/dkim-rsa-private.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCmRB1cn4ksH8Zih8Otd4kE4nVidkIMlgGMso1c5pPnhTJuwOeU\n0Q4DdqqdDGQOERWhiIOB+yFJKr6xZDlZwBOGil4U3TbdW2Ek5H5gcDHfvMqMN8lz\nyClg7yrJylGEt84C9VzTzJSjx+XYyBQgmnh900Apc2FyaI4frk2oJfPA+wIDAQAB\nAoGABl92AKbcyyQspnottehvCBDmDvAZeAIH7Syq3nS4Fpe0ZypdtgaNUvSpdXuU\nGjXtblOdNs45aGSLCqGc0SPbm6y5FsajKP6vSfSvEOPbSgWDGB4lNlJvaPuItbr1\nBcB/Q+hrvyeXu9snBlM9gtGw88FjiV5WWXacWHzqbs8ckAECQQDby/ydd7neXNT3\nBz73K1puCVQsVj4IGV28zm9PufBhIeaFcXwH7OoQ/MPOL17DpUGhSonZalTd2MOQ\nAGf8FJt7AkEAwabvgzfWqdQlILlqjPtSrZ836xxVlRVfBimtQ6/3PbPQpcNv4u8e\nhBGyGHvIcVhjFyCNeWHwMhDDh/3JyiO4gQJBALAgkdkNK6AH+4/H+qjN0LUEPLMa\nmLKcwQSe14unj/wF0ld0TNN9AUODiNQcGW/laOX6eOQD1OXA4VTvPmQ9jykCQDIe\nxKrPju2RjLJ1itBGU9W/+bcONFBLobZ0nvV/25vKqFvew1yWyu0fr1qK3wwG9k6M\nDFG4OXSbxh+yXcHFkQECQAstxjwOhGSI8oqeuKeQYLzlUS+GpUeeNGpEQ3nGwhFU\nsvQWt7jlRm4qAwwyM6l9khXT3esH3Xb8phDfmmhleGk=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/dkim-rsa-public.pem",
    "content": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmRB1cn4ksH8Zih8Otd4kE4nVi\ndkIMlgGMso1c5pPnhTJuwOeU0Q4DdqqdDGQOERWhiIOB+yFJKr6xZDlZwBOGil4U\n3TbdW2Ek5H5gcDHfvMqMN8lzyClg7yrJylGEt84C9VzTzJSjx+XYyBQgmnh900Ap\nc2FyaI4frk2oJfPA+wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  {
    "path": "test/fixtures/html.eml",
    "content": "Message-Id: <98EE8341-05D7-4BAD-846B-1A45979B01EA@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-24--712106862\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: html\r\nDate: Mon, 1 Jun 2009 15:04:25 -0400\r\n\r\n\r\n--Apple-Mail-24--712106862\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nthis\r\nis\r\nhtml\r\n--Apple-Mail-24--712106862\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><ul class=\"MailOutline\"><li>this</li><li>is</li><li>html</li></ul></body></html>\r\n--Apple-Mail-24--712106862--\r\n"
  },
  {
    "path": "test/fixtures/image-and-text-attachments.eml",
    "content": "Message-Id: <87F3EA90-48FC-4271-8F49-5C439811B33E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-18--712519815\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: image and text attachments\r\nDate: Mon, 1 Jun 2009 14:57:32 -0400\r\n\r\n\r\n--Apple-Mail-18--712519815\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-18--712519815\r\nContent-Disposition: inline;\r\n\tfilename=chili-pepper.jpg\r\nContent-Type: image/jpeg;\r\n\tx-unix-mode=0644;\r\n\tname=\"chili-pepper.jpg\"\r\nContent-Transfer-Encoding: base64\r\n\r\n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\r\n\r\n--Apple-Mail-18--712519815--\r\n"
  },
  {
    "path": "test/fixtures/image-attachment-only.eml",
    "content": "Message-Id: <28D3B7D9-448B-4907-8B24-96CADB51C0D4@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-17--712577394\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: image attachment only\r\nDate: Mon, 1 Jun 2009 14:56:34 -0400\r\n\r\n\r\n--Apple-Mail-17--712577394\r\nContent-Disposition: inline;\r\n\tfilename=chili-pepper.jpg\r\nContent-Type: image/jpeg;\r\n\tx-unix-mode=0644;\r\n\tname=\"chili-pepper.jpg\"\r\nContent-Transfer-Encoding: base64\r\n\r\n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\r\n\r\n--Apple-Mail-17--712577394--\r\n"
  },
  {
    "path": "test/fixtures/malformed-folded-multibyte-header.eml",
    "content": "MIME-Version: 1.0\r\nFrom: noreply@orders.eset.com\r\nTo: bgvezdtefag@dropmail.me\r\nDate: 18 Oct 2013 23:13:20 +0200\r\nSubject: =?utf-8?B?Tk9EMzIgU21hcnQgU2VjdXJpdHkgLSDQsdC10YHQv9C70LDR?=\r\n =?utf-8?B?gtC90LDRjyDQu9C40YbQtdC90LfQuNGP?=\r\nContent-Type: text/html; charset=utf-8\r\nContent-Transfer-Encoding: base64\r\n\r\nSGVsbG8gd29ybGQK"
  },
  {
    "path": "test/fixtures/message-as-attachment.eml",
    "content": "Message-Id: <AF6A2412-AFCD-4E45-96B0-C1B8C896B2A2@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-19--712443629\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: message as attachment\r\nDate: Mon, 1 Jun 2009 14:58:48 -0400\r\n\r\n\r\n--Apple-Mail-19--712443629\r\nContent-Disposition: attachment;\r\n\tfilename=\"Plain text only\"\r\nContent-Type: message/rfc822;\r\n\tx-mac-hide-extension=yes;\r\n\tx-unix-mode=0666;\r\n\tname=\"Plain text only\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\nMessage-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n\r\n--Apple-Mail-19--712443629--\r\n"
  },
  {
    "path": "test/fixtures/message-image-text-attachments.eml",
    "content": "Message-Id: <285CFC47-B9E2-4B6C-A59C-DD864500F7A6@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-21--712367366\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: message image text attachments\r\nDate: Mon, 1 Jun 2009 15:00:04 -0400\r\n\r\n\r\n--Apple-Mail-21--712367366\r\nContent-Disposition: attachment;\r\n\tfilename=\"Plain text only.eml\"\r\nContent-Type: message/rfc822;\r\n\tx-mac-hide-extension=yes;\r\n\tx-unix-mode=0666;\r\n\tname=\"Plain text only.eml\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\nMessage-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n\r\n--Apple-Mail-21--712367366\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-21--712367366\r\nContent-Disposition: inline;\r\n\tfilename=chili-pepper.jpg\r\nContent-Type: image/jpeg;\r\n\tx-unix-mode=0644;\r\n\tname=\"chili-pepper.jpg\"\r\nContent-Transfer-Encoding: base64\r\n\r\n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\r\n\r\n--Apple-Mail-21--712367366--\r\n"
  },
  {
    "path": "test/fixtures/message-text-html-attachment.eml",
    "content": "Return-Path: <sender@example.com>\r\nFrom: sender@example.com\r\nTo: recipient@example.com\r\nSubject: A message with text, html and a calendar attachment\r\nReply-To: sender@example.com\r\nMime-Version: 1.0\r\nSender: sender@example.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=\"_=4g116a4p31245o2q4h634e3y354m3103=_\"\r\nDate: Tue, 27 Apr 2021 12:45:20 +0200\r\nMessage-ID: <3c52f2b1dd3d53eff90acf73500fc058@someclient.example.com>\r\n\r\n\r\n--_=4g116a4p31245o2q4h634e3y354m3103=_\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"_=513719676i276h6k6a4h1j326j3m5c32=_\"\r\nContent-Disposition: inline\r\n\r\n\r\n--_=513719676i276h6k6a4h1j326j3m5c32=_\r\nContent-Type: text/plain;\r\n\t charset=\"utf-8\"\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Disposition: inline\r\n\r\nsome text\r\n--_=513719676i276h6k6a4h1j326j3m5c32=_\r\nContent-Type: text/html;\r\n\t charset=\"utf-8\"\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Disposition: inline\r\n\r\n<html></html>\r\n--_=513719676i276h6k6a4h1j326j3m5c32=_--\r\n\r\n--_=4g116a4p31245o2q4h634e3y354m3103=_\r\nContent-Transfer-Encoding: base64\r\nContent-Id: <calendar.ics>\r\nContent-Type: text/calendar;\r\n\t method=\"REQUEST\"\r\nContent-Disposition: inline\r\n\r\nQkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vS0JSVy8vQ2FsaWJleCAwLjEuMC8vRU4NClZFUlNJ\r\nT046Mi4wDQpDQUxTQ0FMRTpHUkVHT1JJQU4NCk1FVEhPRDpSRVFVRVNUDQpCRUdJTjpWRVZFTlQN\r\nCkxBU1QtTU9ESUZJRUQ6MjAyMTA0MjdUMTA0NTIwWg0KU0VRVUVOQ0U6MA0KRFRTVEFNUDoyMDIx\r\nMDQyN1QxMDQ1MjBaDQpDUkVBVEVEOjIwMjEwNDI3VDEwNDUyMFoNClNVTU1BUlk6QSB0ZXN0IGV2\r\nZW50DQpPUkdBTklaRVI7Q049c2VuZGVyQGV4YW1wZS5jb206bWFpbHRvOnNlbmRlckBleGFtcGUu\r\nY29tDQpEVFNUQVJUOjIwMjEwNDI3VDEwNDUwMFoNCkRURU5EOjIwMjEwNDI3VDExNDUwMFoNCkFU\r\nVEVOREVFO1JPTEU9Q0hBSVI7UlNWUD1GQUxTRTtDVVRZUEU9SU5ESVZJRFVBTDtQQVJUU1RBVD1B\r\nQ0NFUFRFRDtDTj1zZW5kZXJAZXhhbXBlLmNvbTtYLU5VTS1HVUVTVFM9MDpzZW5kZXJAZXhhbXBl\r\nLmNvbQ0KQVRURU5ERUU7Q1VUWVBFPUlORElWSURVQUw7Uk9MRT1SRVEtUEFSVElDSVBBTlQ7UEFS\r\nVFNUQVQ9TkVFRFMtQUNUSU9OO1JTVlA9DQogVFJVRTtYLU5VTS1HVUVTVFM9MDtDTj1yZWNpcGll\r\nbnRAZXhhbXBlLmNvbTptYWlsdG86cmVjaXBpZW50QGV4YW1wZS5jb20NCkRFU0NSSVBUSU9OOkFu\r\nIEV2ZW50DQpVSUQ6TXpNME5FQjJiMmx6YldGeWRDNW9iMnh2WTI5dExuWnBaR1Z2DQpTVEFUVVM6\r\nQ09ORklSTUVEDQpFTkQ6VkVWRU5UDQpFTkQ6VkNBTEVOREFSDQo=\r\n\r\n--_=4g116a4p31245o2q4h634e3y354m3103=_--\r\n"
  },
  {
    "path": "test/fixtures/mx1.example.com-server.crt",
    "content": "Certificate:\n    Data:\n        Version: 1 (0x0)\n        Serial Number:\n            31:8e:c8:2d:ba:01:b5:15:28:04:3c:a1:dd:33:ab:5a:27:5f:ab:c8\n        Signature Algorithm: NULL\n        Issuer: CN = mx1.example.com\n        Validity\n            Not Before: May 16 21:18:03 2020 GMT\n            Not After : May 14 21:18:03 2030 GMT\n        Subject: CN = mx1.example.com\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                RSA Public-Key: (2048 bit)\n                Modulus:\n                    00:bb:05:07:48:02:d7:58:03:ef:92:44:8e:4c:c6:\n                    27:ba:90:d5:99:fc:56:81:b1:a8:86:9a:8f:72:25:\n                    8d:57:fb:88:91:85:51:5d:0a:6e:5a:f4:a4:fd:05:\n                    1e:34:e6:69:01:da:1a:e4:1d:ac:83:24:13:ed:2b:\n                    19:9a:5d:95:8b:ad:ad:a9:78:63:b7:73:66:84:68:\n                    c8:9d:ea:f2:fc:50:cc:59:7a:48:78:ea:a1:84:7f:\n                    4b:78:fe:d2:b3:1c:19:17:e2:cf:7d:b4:83:44:0a:\n                    de:b6:ca:74:49:3f:43:96:3a:76:5a:c2:c1:99:a6:\n                    bd:c9:a9:be:03:d7:8e:ee:b2:d4:1d:f0:58:50:64:\n                    2a:19:8b:ff:c7:c2:73:30:fe:e1:93:3c:78:ca:eb:\n                    84:a4:86:8b:21:68:cb:9f:99:7d:08:a4:22:b0:09:\n                    db:7d:09:2c:05:f4:08:c9:a9:c7:2e:17:56:f7:38:\n                    a0:3e:7c:87:4e:ab:73:db:90:2b:b1:ad:2c:65:bc:\n                    d7:81:91:bf:10:1a:e1:b7:f7:fa:aa:45:67:ea:4b:\n                    6c:32:0a:a0:07:ee:c1:18:dc:ef:87:64:2f:38:29:\n                    e4:9b:99:6d:54:0a:e5:5d:17:ff:8b:93:93:99:41:\n                    1f:d7:f7:75:c6:42:3b:4c:54:33:df:b3:b5:02:5f:\n                    82:db\n                Exponent: 65537 (0x10001)\n    Signature Algorithm: NULL\n-----BEGIN CERTIFICATE-----\nMIICtzCCAZ8CFGRw6yad+vUwLqDiy4+RbV7yHKOiMA0GCSqGSIb3DQEBCwUAMBYx\nFDASBgNVBAMMC2dlbl9zbXRwIENBMB4XDTIwMDUxNjIxMTgwM1oXDTMwMDUxNDIx\nMTgwM1owGjEYMBYGA1UEAwwPbXgxLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAuwUHSALXWAPvkkSOTMYnupDVmfxWgbGohpqPciWN\nV/uIkYVRXQpuWvSk/QUeNOZpAdoa5B2sgyQT7SsZml2Vi62tqXhjt3NmhGjInery\n/FDMWXpIeOqhhH9LeP7SsxwZF+LPfbSDRAretsp0ST9Dljp2WsLBmaa9yam+A9eO\n7rLUHfBYUGQqGYv/x8JzMP7hkzx4yuuEpIaLIWjLn5l9CKQisAnbfQksBfQIyanH\nLhdW9zigPnyHTqtz25Arsa0sZbzXgZG/EBrht/f6qkVn6ktsMgqgB+7BGNzvh2Qv\nOCnkm5ltVArlXRf/i5OTmUEf1/d1xkI7TFQz37O1Al+C2wIDAQABMA0GCSqGSIb3\nDQEBCwUAA4IBAQAphvOZwnBGErH/BZYDb2Vl2VouW/UuB1dQagdSdLv5s6BFR8cf\nYSEUo0w4e0rStlzQcifjcKsVa9s0dXTFscXuk4LV3fEdd1Jmt4fvYs9BEc4fFget\nU6847me3jJ8cGi5OOzeVoyUNUV7/uj3xIde0nm+U03L52lrfdlsi2gM5486Z1crq\nOlY6TQTPmbVBqMlGZUQ42jAtndJjyA9qqIH5xpfWUaoFr9hY7Qc2DSZFZb8BDTty\nmRd2OjUiwCjInWN/LANSKWSUCveGUffIW+TZPhsuyNB5V1XS/zdLjS/BnAx6NLvr\nG4m1Wbug20VRCNV4fAZGNOF5kw+miYrwZ0HS\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/mx1.example.com-server.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuwUHSALXWAPvkkSOTMYnupDVmfxWgbGohpqPciWNV/uIkYVR\nXQpuWvSk/QUeNOZpAdoa5B2sgyQT7SsZml2Vi62tqXhjt3NmhGjInery/FDMWXpI\neOqhhH9LeP7SsxwZF+LPfbSDRAretsp0ST9Dljp2WsLBmaa9yam+A9eO7rLUHfBY\nUGQqGYv/x8JzMP7hkzx4yuuEpIaLIWjLn5l9CKQisAnbfQksBfQIyanHLhdW9zig\nPnyHTqtz25Arsa0sZbzXgZG/EBrht/f6qkVn6ktsMgqgB+7BGNzvh2QvOCnkm5lt\nVArlXRf/i5OTmUEf1/d1xkI7TFQz37O1Al+C2wIDAQABAoIBAA3tvPIXDBTJDkG1\ni2eaZoEVomL6kTLNmYCU6FQXCeTgnfZAmKO2UCvEBrm1dN95vZ5esRwGPb/you1K\nBXkiuS2S/NkfV0XleWApMa/ZPMmf9ug/HECtMOReWq+jQuwGDrRhtxRkqlYZ/SZe\nA7Uk2hLJPeFamfKooX/wfW9p0YJjfKK+SFaydSwEEYj7lUZtVJicI6X0YMSUE3WH\nI9rpgPvoPYvtv1JIcxrJRWPSRQwkMrwnJQRpOaGPkVockSISC3vmRzY10IJbLuNP\nkUHIOw9kmjM8fnKZbiNzYKViB/b1J8x1mvBTGLRAd7VL8iM5u9NY80Gg2P9OtBex\nYpw+nnECgYEA3LBzAHi02yG3gg5LIm1S2rQR1fscDQzvsk8i3TqWooM3277wTE2n\ng3rANdK4en7L9tptVkguauqHASS8Dyi4xkBwMfmRXlCFS02YHgA1Qi5UKWQLCDoH\nG8SLK90o7zkUE6PZNV40zDuIzZGPaC69Iox16wSY3Yh9aGXOIOeh93kCgYEA2PF0\nKQ9KZ6V5QTJM+ejTd3s2ylpTLeeUvz9VimzpeV2M7bfqcplkNUAGPL94XFhf8Q+i\nyjixIYrWuW5m2VC4hsV9J8mCC3Vi23bH47n7VW3wx1mUTOc+aLSWXJBxnuA9RSkw\nOiqzy6WQCVdx3lxPEQLgfoF1npU6bPGPBeJYs/MCgYAD9caag4/7PqekVc1TWNLb\nyc9oH5FpSooikPj3L030rJYcA1kchWg0G8fHL3jP+eZ/D3xWyATNNlgl1RrqyrhG\nFnHs86WAI8HAkCvine5Wua4Y8Aqioyftf6FfsCBD6qpJj+8d3grkf0z9I1eHbw9F\nx292QCbeEsztSqZgQMfPQQKBgQCyvjYUAnoubYM7OWN84N0i640YKlWwU8cVz+v9\n0oCHM5IC5u6vHz0WNrss4CEeDN53sodREGa5GTiTrafl04FF4X+eAYQ5Rq193x8Q\nvVKcb6nbxi3PMxQTlv7wIz7KRT2WNzp6ImbjGnVTjQ3PxMSMYo9vC+FKGO/7hQdv\nNLAbCwKBgDnGLV6t6Js0g6LWPPis3cp4HR7DI1Cc3pD3XfxPE6bttgjjWhxDN3w2\n5ZSqvJ1whwnr/tWKCcmdYLP8YPqtZmaKB8PLplGaeqCMANE9tnCszZCjvMEjdAsQ\n7QKCG5UXuU7ALTcK8LJCyJFL/eV8vBclZzyobb6optwLzsbNBDY7\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/mx2.example.com-server.crt",
    "content": "Certificate:\n    Data:\n        Version: 1 (0x0)\n        Serial Number:\n            28:83:38:42:8a:43:38:6b:12:fb:48:d3:5b:37:d5:9c:c2:59:de\n        Signature Algorithm: NULL\n        Issuer: CN = mx2.example.com\n        Validity\n            Not Before: May 16 21:18:03 2020 GMT\n            Not After : May 14 21:18:03 2030 GMT\n        Subject: CN = mx2.example.com\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                RSA Public-Key: (2048 bit)\n                Modulus:\n                    00:b5:5c:02:6c:85:d3:4f:7c:32:ff:d9:f3:5f:ac:\n                    7c:42:89:b3:61:68:95:fd:8c:d0:4b:75:ab:46:5a:\n                    84:1e:b9:92:fe:44:4a:3a:53:d2:a7:5e:5a:43:67:\n                    0c:83:fb:54:0b:1b:13:05:8b:32:82:da:7d:bf:1f:\n                    8d:9c:02:20:bb:dc:f5:27:99:ce:6c:45:5e:cb:b3:\n                    3e:9d:98:1d:87:72:9f:56:b4:46:1e:10:d4:fa:13:\n                    d1:97:96:35:3c:dc:3a:57:b9:69:44:37:6a:f1:0e:\n                    1d:44:d3:32:bf:dd:b4:3a:04:02:59:67:03:6b:96:\n                    72:12:dc:24:6a:72:ee:05:f7:82:ff:68:1c:0c:cd:\n                    75:69:87:7c:6f:f2:92:36:56:ca:09:c5:cc:6c:9b:\n                    73:27:45:0b:50:09:c4:6a:20:53:13:11:51:40:52:\n                    8e:ce:49:a1:82:26:bc:c3:33:76:79:e4:e0:5c:b8:\n                    17:a9:d9:e9:de:d8:75:67:98:86:00:2b:fa:76:ab:\n                    1e:4d:5c:4a:e9:f3:6a:7f:56:c8:a7:38:24:d5:36:\n                    71:96:68:0c:ce:e8:a5:64:34:25:42:d5:b8:a7:7c:\n                    76:03:ae:7c:f1:36:30:cf:b6:d5:27:5a:1a:37:8b:\n                    53:6a:3d:a1:0b:41:b8:8b:f1:d6:66:3e:3c:a7:4d:\n                    a3:8b\n                Exponent: 65537 (0x10001)\n    Signature Algorithm: NULL\n-----BEGIN CERTIFICATE-----\nMIICtzCCAZ8CFGRw6yad+vUwLqDiy4+RbV7yHKOjMA0GCSqGSIb3DQEBCwUAMBYx\nFDASBgNVBAMMC2dlbl9zbXRwIENBMB4XDTIwMDUxNjIxMTgwM1oXDTMwMDUxNDIx\nMTgwM1owGjEYMBYGA1UEAwwPbXgyLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAtVwCbIXTT3wy/9nzX6x8QomzYWiV/YzQS3WrRlqE\nHrmS/kRKOlPSp15aQ2cMg/tUCxsTBYsygtp9vx+NnAIgu9z1J5nObEVey7M+nZgd\nh3KfVrRGHhDU+hPRl5Y1PNw6V7lpRDdq8Q4dRNMyv920OgQCWWcDa5ZyEtwkanLu\nBfeC/2gcDM11aYd8b/KSNlbKCcXMbJtzJ0ULUAnEaiBTExFRQFKOzkmhgia8wzN2\neeTgXLgXqdnp3th1Z5iGACv6dqseTVxK6fNqf1bIpzgk1TZxlmgMzuilZDQlQtW4\np3x2A6588TYwz7bVJ1oaN4tTaj2hC0G4i/HWZj48p02jiwIDAQABMA0GCSqGSIb3\nDQEBCwUAA4IBAQBSj0lWVI41JkfomBA7b/1pvKwckpCr813n7GJEScP0etPSyTze\nZWHJ2gE/QddmGm2jXkyOfNiPSRcAmJrjuZSE1yNJGFDSsIu5aYZOy5NWZp0dvh/4\n0HJlBXHMAAYmpahM6D8JCzlGPJPqKF5K0zJmleivBpJNAcjhWLas7QIpVbs26jCm\n+SJiQ5prGykbur4+NanKZoNeCADsTEbACK9KzZMSz9kt9tCEWwHHCf9WIe2m67FI\nadM1X/qf7lXdAfGg38vWTuloyROrxHwl2MIXx/H3ayI8uPZ7VfC6FnDfZhq5u1jp\nDkv2FdNv0LKUJBjMKv9KL6cSzisV+mDOFv8k\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/mx2.example.com-server.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtVwCbIXTT3wy/9nzX6x8QomzYWiV/YzQS3WrRlqEHrmS/kRK\nOlPSp15aQ2cMg/tUCxsTBYsygtp9vx+NnAIgu9z1J5nObEVey7M+nZgdh3KfVrRG\nHhDU+hPRl5Y1PNw6V7lpRDdq8Q4dRNMyv920OgQCWWcDa5ZyEtwkanLuBfeC/2gc\nDM11aYd8b/KSNlbKCcXMbJtzJ0ULUAnEaiBTExFRQFKOzkmhgia8wzN2eeTgXLgX\nqdnp3th1Z5iGACv6dqseTVxK6fNqf1bIpzgk1TZxlmgMzuilZDQlQtW4p3x2A658\n8TYwz7bVJ1oaN4tTaj2hC0G4i/HWZj48p02jiwIDAQABAoIBAEh6V+Gk7djzKrKD\nGLcgiJxSyaRhFqg4sTmm8ebw36IjybHh+sQqoaIPnAUZ1q+cLm8tx8FMashOpzhN\nVNuHIivR1wuXdR5h7st7e8ehdhOeZD1TWD5FvcefSgDJn8cNwCc0yvPfLdbeLCZI\nPRzebltNJN8zwvMpMbeF0OvVuHgbUOtgiw37QW7/FWXQz8RjfDntxAjLPGDUS/lP\n2DEbpJ6U5b2FfGLCkmMBKVcu8THcoQVf3LUkQWzK0Dk6OEaSJxQLfQ1O6x5DkNd3\nYgV8pws6pSWZz+XX8i4uUNp0G4/CnrRtOq3H9R+3wd/X6nSEIurAQUPUZPZ31+Jm\nsxHz8XkCgYEA5SFo7tribSBL7UQBJv2pKwfTrVLTBFw47M7Q8S4SJAHoIFZjT9Un\ng1Ra2d32m50XN23Rw0p+5TkUEeyHMt/8MI5S1yRCO+s4pbWO+DyCpVV8MhpyQw+M\njUe5pRKJ0YthC476sZpmwMV+FU4SpRmbuEZl1QEb+tQzgRODXPPKf7cCgYEAyqB9\n9xa+C/fxsM5hg+FQBpUUQ36zUYmy/6GlMDztS7umW7Yq2dNnmjCxrYsvEcRXApzi\nYUPKz8cQ5u0AwJS42RrS5XBHZcobiKL0YWGpPt9BWusdSocmI7jQfEB5MmwlwKfI\nodZM+vdHt8nvecPrDoR9c9rIxP2/0MfUrGspks0CgYASVYYL9r+/c6Ifrh1ZfVqX\n8txhNgtkgeycJkBZzBHvh6eHTuJLdQbgX1OVs0kUUpGVAdiTA9b7iIGunXqD+6A2\nUm0WgfQ6zyuNNuXlvxHFIP37FFqoOwpIE8ErEDyu47Q0NJCivXQTYLoiAklDpLTt\nHdTwIlKW03v7jBAq0+cUKQKBgQCEjr4ZeX1W4xvwaPOOjUYHKFwbU7YH76d0aNFi\nX1l2JArPELuzyQOL8bMrL1TZsLKjePL4Yps5lqdOC1pkombTUSMLCosK4k9k8gYh\n9vv7r55X1lxRN10SHYP25U7kV6/S+3DbvxCZVlBKwgayiCMsWiygME8L4F0uPqy5\nJ1oJOQKBgCnpsspw18AOSiL8AJqOg5Wjut8e9qPnES8Qo0j8NasVL2GyffzNsaD9\nA2paaVG3NUUscE38I8XzlCNPluhTfoMiL+wBkbXT7AAvc7QX3+aKA82ezv3NkJX3\nkcvg5jKjLo0szTGdUqgVNgwYg9izKIJ54tKz5MfTUeepRQFxAvVT\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/outlook-2007.eml",
    "content": "Message-ID: <000001ca269e$bed3a4b0$3c7aee10$@com>\r\nFrom: \"Jack Danger Canty\" <local@localhost.com>\r\nTo: <gen_smtp@localhost.com>\r\nSubject: outlook sending to http://jackcanty.com\r\nDate: Wed, 26 Aug 2009 15:44:00 -0700\r\nMIME-Version: 1.0\r\nContent-Type: multipart/alternative;\r\n\t boundary=\"----=_NextPart_000_0001_01CA2664.1274CCB0\"\r\nX-Mailer: Microsoft Office Outlook 12.0\r\nThread-Index: AcomnrHFkIUUMZYfRny1J0mKT9Z5ig==\r\nContent-Language: en-us\r\nx-cr-hashedpuzzle: AyWi BJ8p BfTL ByBH B9cB B/Er CU+B CoJu DJ7t Di6e FBtz FraZ F3A5 INmb Jggw J2aV;\r\n\t1;\r\n\tcwB0AHUAZABpAG8AZABhAG4AZwBlAHIAQABnAG0AYQBpAGwALgBjAG8AbQA=;\r\n\tSosha1_v1;\r\n\t7;\r\n\t{98C29171-D6F7-4531-9A6E-59B1C4C98AD8};\r\n\tagBhAGMAawBAAGEAZABwAGkAYwBrAGwAZQBzAC4AYwBvAG0A;\r\n\tWed, 26 Aug 2009 12:01:18 GMT;\r\n\tUgB1AG4AbgBpAG4AZwAgAHcAaQB0AGgAIABhAHQAdABhAGMAaABtAGUAbgB0AHMAIAB0AGgAcgBvAHUAZwBoACAAdABoAGUAIAByAGUAbQBvAHQAZQAgAHMAZQByAHYAZQByACAAdwBpAHQAaAAgAE8AdQB0AGwAbwBvAGsAIAAyADAAMAA3AA==\r\nx-cr-puzzleid: {98C29171-D6F7-4531-9A6E-59B1C4C98AD8}\r\n\r\n\r\nThis is a multipart message in MIME format.\r\n\r\n\r\n------=_NextPart_000_0001_01CA2664.1274CCB0\r\nContent-Type: text/plain;\r\n\t charset=\"us-ascii\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\noutlook\r\n\r\n\r\n------=_NextPart_000_0001_01CA2664.1274CCB0\r\nContent-Type: text/html;\r\n  charset=\"us-ascii\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n<html xmlns:v=3D\"urn:schemas-microsoft-com:vml\" =\r\nxmlns:o=3D\"urn:schemas-microsoft-com:office:office\" =\r\nxmlns:w=3D\"urn:schemas-microsoft-com:office:word\" =\r\nxmlns:m=3D\"http://schemas.microsoft.com/office/2004/12/omml\" =\r\nxmlns=3D\"http://www.w3.org/TR/REC-html40\">\r\n\r\n<head>\r\n<META HTTP-EQUIV=3D\"Content-Type\" CONTENT=3D\"text/html; =\r\ncharset=3Dus-ascii\">\r\n<meta name=3DGenerator content=3D\"Microsoft Word 12 (filtered medium)\">\r\n<style>\r\n<!--\r\n /* Font Definitions */\r\n @font-face\r\n\t{font-family:Calibri;\r\n\tpanose-1:2 15 5 2 2 2 4 3 2 4;}\r\n /* Style Definitions */\r\n p.MsoNormal, li.MsoNormal, div.MsoNormal\r\n\t{margin:0in;\r\n\tmargin-bottom:.0001pt;\r\n\tfont-size:11.0pt;\r\n\tfont-family:\"Calibri\",\"sans-serif\";}\r\na:link, span.MsoHyperlink\r\n\t{mso-style-priority:99;\r\ncolor:blue;\r\n\ttext-decoration:underline;}\r\na:visited, span.MsoHyperlinkFollowed\r\n\t{mso-style-priority:99;\r\n\tcolor:purple;\r\n\ttext-decoration:underline;}\r\nspan.EmailStyle17\r\n\t{mso-style-type:personal-compose;\r\n\tfont-family:\"Calibri\",\"sans-serif\";\r\n\tcolor:windowtext;}\r\n..MsoChpDefault\r\n\t{mso-style-type:export-only;}\r\n@page Section1\r\n\t{size:8.5in 11.0in;\r\n\tmargin:1.0in 1.0in 1.0in 1.0in;}\r\ndiv.Section1\r\n\t{page:Section1;}\r\n-->\r\n</style>\r\n<!--[if gte mso 9]><xml>\r\n <o:shapedefaults v:ext=3D\"edit\" spidmax=3D\"1026\" />\r\n</xml><![endif]--><!--[if gte mso 9]><xml>\r\n <o:shapelayout v:ext=3D\"edit\">\r\n  <o:idmap v:ext=3D\"edit\" data=3D\"1\" />\r\n </o:shapelayout></xml><![endif]-->\r\n</head>\r\n\r\n<body lang=3DEN-US link=3Dblue vlink=3Dpurple>\r\n\r\n<div class=3DSection1>\r\n\r\n<p class=3DMsoNormal>outlook<o:p></o:p></p>\r\n\r\n</div>\r\n\r\n</body>\r\n\r\n</html>\r\n\r\n------=_NextPart_000_0001_01CA2664.1274CCB0--\r\n"
  },
  {
    "path": "test/fixtures/plain-text-and-two-identical-attachments.eml",
    "content": "Message-Id: <89F3FAFA-5772-4B76-83A7-C1D997EA483E@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-31--702924118\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: plain text and two identical attachments\r\nDate: Mon, 1 Jun 2009 17:37:28 -0400\r\n\r\n\r\n--Apple-Mail-31--702924118\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains only plain text.\r\n\r\n--Apple-Mail-31--702924118\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-31--702924118\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-31--702924118--\r\n"
  },
  {
    "path": "test/fixtures/python-smtp-lib.eml",
    "content": "Content-Type: text/plain; charset=\"us-ascii\"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nSubject: A trame\r\nFrom: hello@ytotech.com\r\nTo: test@ytotech.com\r\n\r\nHello world Python.\r\n"
  },
  {
    "path": "test/fixtures/rich-text-bad-boundary.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798g\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/rich-text-broken-last-boundary.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798\r\n"
  },
  {
    "path": "test/fixtures/rich-text-missing-first-boundary.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/rich-text-missing-last-boundary.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n"
  },
  {
    "path": "test/fixtures/rich-text-no-MIME.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/rich-text-no-boundary.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/rich-text-no-text-contenttype.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/rich-text.eml",
    "content": "Message-Id: <E25EB012-E950-4285-8DD4-DC19F6603AD8@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-14--712713798\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: rich text only\r\nDate: Mon, 1 Jun 2009 14:54:18 -0400\r\n\r\n\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis message contains rich text.\r\n--Apple-Mail-14--712713798\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This </b><i>message </i><span class=\"Apple-style-span\" style=\"text-decoration: underline;\">contains </span>rich text.</body></html>\r\n--Apple-Mail-14--712713798--\r\n"
  },
  {
    "path": "test/fixtures/root.crt",
    "content": "Certificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number:\n            7e:07:a0:b6:b6:65:38:94:b9:54:4c:c3:d6:26:ae:9e:07:6b:3c:3c\n        Signature Algorithm: sha256WithRSAEncryption\n        Issuer: CN = gen_smtp CA\n        Validity\n            Not Before: May 16 21:18:03 2020 GMT\n            Not After : May 14 21:18:03 2030 GMT\n        Subject: CN = gen_smtp CA\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                RSA Public-Key: (2048 bit)\n                Modulus:\n                    00:b7:b9:5e:ed:d6:3d:98:18:93:80:61:bd:ab:3b:\n                    54:6f:4a:c1:f1:e0:d7:b9:03:3b:79:45:a8:01:f3:\n                    49:00:20:8d:c3:c0:c0:d3:03:eb:0f:3c:a3:8e:d7:\n                    18:6d:bd:f7:c8:59:6e:b4:6c:c2:50:f2:e3:a9:e3:\n                    ae:9f:cf:69:f0:ca:80:be:84:fa:99:35:95:ba:f9:\n                    ea:75:fc:c8:20:13:eb:b8:b6:82:3c:04:a7:78:85:\n                    23:3a:2e:d8:d1:91:59:31:52:38:57:c4:f1:52:38:\n                    b9:bf:5b:e9:a1:86:ab:fc:69:1a:8b:9e:f7:99:40:\n                    3a:21:b8:04:d8:f0:72:f4:2c:d3:aa:97:52:16:20:\n                    1e:2c:43:91:93:a4:c5:c9:62:5b:15:4e:28:2b:9b:\n                    97:d1:70:e8:90:a9:7b:ae:94:ca:73:59:08:09:6c:\n                    c8:45:e2:e5:0a:72:c3:ab:ba:fa:15:f5:e7:ff:67:\n                    ac:ca:56:71:59:41:1c:e7:c2:6c:73:a3:35:4e:7b:\n                    24:37:18:4f:7e:94:f7:24:d1:c9:c7:02:00:60:94:\n                    d9:7f:12:2f:be:9c:93:f9:e1:ed:f5:8f:b8:b1:bb:\n                    b7:9c:8a:a8:4b:f1:f3:2d:32:48:2f:62:00:ce:3f:\n                    59:1c:fb:7c:48:c0:ce:43:23:9c:99:2b:6f:67:9c:\n                    5f:e1\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Subject Key Identifier: \n                BB:3F:4C:FF:39:C8:53:92:FC:9E:A8:11:89:60:92:C8:D0:6E:3C:52\n            X509v3 Authority Key Identifier: \n                keyid:BB:3F:4C:FF:39:C8:53:92:FC:9E:A8:11:89:60:92:C8:D0:6E:3C:52\n\n            X509v3 Basic Constraints: critical\n                CA:TRUE\n    Signature Algorithm: sha256WithRSAEncryption\n         89:9c:f5:02:16:5c:5e:53:68:13:f0:9f:4d:95:f8:08:a0:cc:\n         d9:fb:d0:c6:38:10:74:3d:43:e5:a8:19:ae:11:d8:df:84:d0:\n         11:de:2b:32:1f:31:b9:0b:04:f0:8d:f9:97:74:c8:94:06:fc:\n         77:26:09:67:98:c8:1a:1d:73:a7:d5:43:b3:00:9e:78:72:ae:\n         e7:b5:23:f0:7e:08:ff:dd:13:a5:5c:05:b1:0a:87:6c:44:9f:\n         97:61:c2:95:d0:6a:c7:52:2d:80:fe:da:62:98:78:b6:b5:56:\n         73:92:35:16:26:5f:ca:8e:96:f0:ec:a9:1b:da:fb:05:fc:73:\n         a7:b7:92:bd:24:2e:07:e8:62:c7:0b:f1:8f:bc:23:9d:1c:bc:\n         5a:91:70:4c:a0:af:bf:03:f2:18:e8:86:74:f3:2a:c0:42:be:\n         23:86:38:8b:f7:3e:60:6c:4a:99:d7:f7:b9:de:23:7c:15:eb:\n         c3:ae:97:38:cf:ab:94:19:33:d1:54:f8:82:da:58:dd:c1:fa:\n         07:fe:4b:ad:9c:a1:5c:d8:cd:a3:81:59:e9:d4:56:15:d4:66:\n         0d:e2:91:fc:94:2d:2f:aa:e5:91:ad:7b:5d:1a:04:50:6a:55:\n         82:94:7e:f8:ad:a8:fb:77:40:82:85:a5:fa:4a:a2:7b:ab:54:\n         fe:11:96:38\n-----BEGIN CERTIFICATE-----\nMIIDDTCCAfWgAwIBAgIUfgegtrZlOJS5VEzD1iaungdrPDwwDQYJKoZIhvcNAQEL\nBQAwFjEUMBIGA1UEAwwLZ2VuX3NtdHAgQ0EwHhcNMjAwNTE2MjExODAzWhcNMzAw\nNTE0MjExODAzWjAWMRQwEgYDVQQDDAtnZW5fc210cCBDQTCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBALe5Xu3WPZgYk4Bhvas7VG9KwfHg17kDO3lFqAHz\nSQAgjcPAwNMD6w88o47XGG2998hZbrRswlDy46njrp/PafDKgL6E+pk1lbr56nX8\nyCAT67i2gjwEp3iFIzou2NGRWTFSOFfE8VI4ub9b6aGGq/xpGoue95lAOiG4BNjw\ncvQs06qXUhYgHixDkZOkxcliWxVOKCubl9Fw6JCpe66UynNZCAlsyEXi5Qpyw6u6\n+hX15/9nrMpWcVlBHOfCbHOjNU57JDcYT36U9yTRyccCAGCU2X8SL76ck/nh7fWP\nuLG7t5yKqEvx8y0ySC9iAM4/WRz7fEjAzkMjnJkrb2ecX+ECAwEAAaNTMFEwHQYD\nVR0OBBYEFLs/TP85yFOS/J6oEYlgksjQbjxSMB8GA1UdIwQYMBaAFLs/TP85yFOS\n/J6oEYlgksjQbjxSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB\nAImc9QIWXF5TaBPwn02V+AigzNn70MY4EHQ9Q+WoGa4R2N+E0BHeKzIfMbkLBPCN\n+Zd0yJQG/HcmCWeYyBodc6fVQ7MAnnhyrue1I/B+CP/dE6VcBbEKh2xEn5dhwpXQ\nasdSLYD+2mKYeLa1VnOSNRYmX8qOlvDsqRva+wX8c6e3kr0kLgfoYscL8Y+8I50c\nvFqRcEygr78D8hjohnTzKsBCviOGOIv3PmBsSpnX97neI3wV68OulzjPq5QZM9FU\n+ILaWN3B+gf+S62coVzYzaOBWenUVhXUZg3ikfyULS+q5ZGte10aBFBqVYKUfvit\nqPt3QIKFpfpKonurVP4Rljg=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/root.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAt7le7dY9mBiTgGG9qztUb0rB8eDXuQM7eUWoAfNJACCNw8DA\n0wPrDzyjjtcYbb33yFlutGzCUPLjqeOun89p8MqAvoT6mTWVuvnqdfzIIBPruLaC\nPASneIUjOi7Y0ZFZMVI4V8TxUji5v1vpoYar/Gkai573mUA6IbgE2PBy9CzTqpdS\nFiAeLEORk6TFyWJbFU4oK5uX0XDokKl7rpTKc1kICWzIReLlCnLDq7r6FfXn/2es\nylZxWUEc58Jsc6M1TnskNxhPfpT3JNHJxwIAYJTZfxIvvpyT+eHt9Y+4sbu3nIqo\nS/HzLTJIL2IAzj9ZHPt8SMDOQyOcmStvZ5xf4QIDAQABAoIBAF2/UAoqVNmkSLes\nqByUtJvpWJd0tH7qgFF8UqNUIb7X3Z6yX3INQMdQmODNLuDom2P3Bn84M9scZUEO\nNc/EBXnhytnsfvbomdODrLix2OhNYe2p60B224Gq5fPNbcNZ2FpLawaWLtFWsqlL\nXCaY0m+Erg/qeMsRM9h6zrZn0zB2RdxtaVGrfHwGbB5gDJnm9bdCICAOr+4HRUXM\nL2Hd0fZJeRPw0yuhAU5uswMxlqKiRHfTAMbockIJxrZ7XOJpv82Aw3ENJTiCZaNJ\n1kHfgE3K/Td1CPajsg/T68Nh4CrT36wmYm81fGmkvRMcsNqR0zO+jr5OkEsG5DeR\nQZ4vskUCgYEA3HPmPjGeNFbFNeeSNjHcKr12dnqkFlFHKQKdeSp7srlz1/VXWkZ2\nTZtXT1E87f+RkhUJAanmGrHRmreFSTxyUfB28Hj7PSvO1JM+YgWVu9RBwhVKshou\nOSwGhOSVuK+xvc4mQSZ9Zjy43d0WFQN3wORvMJuQawaLCERoQN7oYp8CgYEA1VlY\nVQH7VSBY+e5hliM0pdWofxSzfxtRkZWdTjf2+2qHm2EWvttfyOYnhAwwi+ncqRD+\npM3cE9m1Hq7nA09kYDkLdbG5C7JOmr5ZDXizHbAOoVmj2DjUxuKKsE3Q11CW4+eA\nRXNuuFn2eVmUGleCTviLS/QBbuoEZPjZfteSrX8CgYEAysQTdwr+P5e7xmvbcNuF\nbQ5cwnblK93QPOk53DN2GRo4cd8oXFFJCPKjaMII78NMqneMlCooCk+ZwdugzY66\ne6FYVLCCLW54y88u5svKQDvny9L3pD8uWsmiqWLyTy/SpQjS6MO1PW8GfpKWd/d7\nk0DJAIVlXPtkr9LzrQ8Z4XMCgYAmcj1KxFqoUnX2RBDt31ZDdCczD2XxR9kBJTb9\nu3QUhnP9eheBOUMfjuocD55H+FK9XMSmqjo4kYjkCJy0qf/qnx0Djo1MIEut8xNV\nLCUK+okIZoDyG/usA3L+pmc2Bd3LIBKrcUvIiN2zrILV5GMlHADuJQCFHkLAd1+q\nTequvQKBgQDLBd05624BHSkis0fQdlCKSrhiWg+EuC82rZrqh7iGheBSxzw8tZ6p\nC0Y3F/v/wknoJkizpmo0IGf+IBc2eUZJu6SUkHCAtGQvyMrmAxgLCd38qJtSX8mW\nsARKO5kHxKgIbFnRdXiDjWM8c9wJ/fwZcgvWLllSlylIUvZjFLcYYg==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/server.key.secure",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,1D3CBB1EF434EE2C\n\n7hd73/uaw35sfG58EW8HX3Fg3drP5RVhMp+GwqmdDdeh/vTyF1gVRD0SugrgWVin\nb44Vw3wgltMLn9m2ReJqPXlhX5/hXMGe7YGO6jeJ4w7u9hEDHpIMTxFfSmsTgiwL\nJmCP340Cz8lVBlfgy4tH3b1Ddi1Yu5dr0xF2X/sTrhREnx744x2oHxQwzxX0pauC\nCG2GiNfah67KfeNYieiuwPGqZaW6yIuITMtfiwDZARurZDXUbD3frXphB5yo/5T/\nRcpcbhFwJhoUFapXWeZNNtQyc12xj/olyLI9jCu5HpY5AGaRwv5IAMwSEMzJW/Ea\nnadtI044zhnTonbJL2DtikfwbQ46BmMXnTtHNQTyVdqYDUT6wQdu0FyLSZSTOhEf\nD05zrQYzhGGuGzXDjIf4uU+vBUoqzIa64nf2+wFtSKQ=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/shift-jismail",
    "content": "Return-Path: <ejozkbcityvs@mpw-germany.com>\r\nX-Original-To: andrew@hijacked.us\r\nDelivered-To: andrew@hijacked.us\r\nReceived: from bd3dfe4f.virtua.com.br (unknown [189.61.254.79])\r\n\tby hijacked.us (Postfix) with SMTP id E01BFB3D3\r\n\tfor <andrew@hijacked.us>; Fri, 27 Mar 2009 19:03:28 -0400 (EDT)\r\nReceived: from 176.236.175.250 by 189.61.254.79; Sat, 28 Mar 2009 02:01:26 +0200\r\nMessage-ID: <NZXEFZHMPQPZLONRWISJSD@japanlifeline.com>\r\nFrom: \"=?ISO-2022-JP?B?RC1MT1ZFGyRCMT8xRCU5JT8lQyVVGyhC?=\" <ejozkbcityvs@mpw-germany.com>\r\nReply-To: \"=?ISO-2022-JP?B?RC1MT1ZFGyRCMT8xRCU5JT8lQyVVGyhC?=\" <ejozkbcityvs@mpw-germany.com>\r\nTo: andrew@hijacked.us\r\nSubject: =?ISO-2022-JP?B?GyRCQGgkOjtPJGEka0EwJEtJLCQ6JCpGSSRfMjwkNSQkISMbKEI=?=\r\nDate: Sat, 28 Mar 2009 02:55:26 +0300\r\nX-Mailer: The Bat! (v1.52f) Business\r\nMIME-Version: 1.0\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"--=_cgXS9SvIcF\"\r\nX-Priority: 3\r\nX-MSMail-Priority: Normal\r\n\r\n----=_cgXS9SvIcF\r\nContent-Type: text/plain; charset=\"shift_jis\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n=8A=AE=91S=96=B3=97=BF=82=C5=81A=91f=93G=82=C8=8Fo=89=EF=82=A2=82=AA=82=C5=\r\n=82=AB=82=C4=81A=82=B3=82=E7=82=C9=91=F2=8ER=82=CC=83C=83x=83=93=83g=82=C9=\r\n=82=E0=8EQ=89=C1=82=AA=82=C5=82=AB=82=E9\r\n=83T=83C=83g=81uD=81|LOVE=81v=82=F0=82=B2=91=B6=92m=82=C5=82=B7=82=A9=81H\r\n\r\n=8E=84=82=CD=81AD-LOVE=89^=89c=83X=83^=83b=83t=82=CC=89Y=93c=82=C6=90\\=82=B5=\r\n=82=DC=82=B7=81B\r\n\r\n=8D=A1=89=F1=8F=D0=89=EE=92v=82=B5=82=DC=82=B7=82=CC=82=CD=81A=81wD-LOVE=81=\r\nx=82=C6=8C=BE=82=A4=83T=83C=83g=82=C5=8C=E4=8D=C0=82=A2=82=DC=82=B7=81B\r\n\r\n=81y=81@D-LOVE=83T=83C=83g=89=E6=96=CA=81Fhttp://www.bizworkss.com/dlove=81=\r\n@=81z\r\n\r\n=88=AB=93=BF=8Ds=88=D7=82=C8=82=C7=82=CD=88=EA=90=D8=8C=E4=8D=C0=82=A2=82=DC=\r\n=82=B9=82=F1=82=CC=82=C5=81A\r\n=83X=83g=83=8C=81[=83g=82=C9=82=B2=8F=D0=89=EE=82=B5=82=DC=82=B7=81B\r\n\r\n=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=\r\n=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=\r\n=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96\r\n\r\n=81=A1=8A=AE=91S=96=B3=97=BF=81A=83=81=81[=83=8B=82=CC=82=E2=82=E8=8E=E6=82=\r\n=E8=82=C9=90=A7=8C=C0=82=CD=8C=E4=8D=C0=82=A2=82=DC=82=B9=82=F1=81B\r\n\r\n=81E=92j=8F=97=82=C6=82=E0=82=C9=83T=83C=83g=93=E0=82=C5=82=CC=81A=8B@=94\\=\r\n=82=CD=91S=82=C4=96=B3=97=BF=82=C5=82=B2=97=98=97p=82=A2=82=BD=82=BE=82=AF=\r\n=82=DC=82=B7=81B\r\n=81E=88=EA=94=D4=8Fd=97v=82=C8=81A=83=81=81[=83=8B=82=CC=82=E2=82=E8=8E=E6=\r\n=82=E8=82=E0=8DD=82=AB=82=C8=82=BE=82=AF=82=B2=97=98=97p=82=C5=82=AB=82=DC=\r\n=82=B7=81B\r\n\r\n=81=A1=97=98=97p=95=FB=96@=82=AA=8A=C8=92P=82=C5=8Cg=91=D1=82=A9=82=E7=82=E0=\r\n=82=B2=97=98=97p=82=AA=82=C5=82=AB=82=E9=82=CC=82=C5=83X=83O=82=C9=82=C5=82=\r\n=E0=82=A8=91=8A=8E=E8=82=CC=95=FB=82=C6=82=A8=89=EF=82=A2=82=C5=82=AB=82=DC=\r\n=82=B7=81B\r\n\r\n=81E=83T=83C=83g=93=E0=82=CC=8B@=94\\=82=CD=8A=C8=92P=82=C9=94c=88=AC=82=C5=\r\n=82=AB=81A=8A=C8=92P=82=C9=82=E2=82=E8=8E=E6=82=E8=82=C8=82=C7=82=F0=8En=82=\r\n=DF=82=C4\r\n=81E=92=B8=82=AD=8E=96=82=AA=82=C5=82=AB=82=E9=82=CC=82=C5=81A=83X=83=80=81=\r\n[=83Y=82=C9=82=E2=82=E8=8E=E6=82=E8=82=AA=82=C5=82=AB=82=DC=82=B7=81B\r\n\r\n=81E=8Cg=91=D1=82=A9=82=E7=82=CC=82=B2=97=98=97p=82=E0=82=C5=82=AB=82=DC=82=\r\n=B7=82=CC=82=C5=81A=82=C7=82=B1=82=A9=82=E7=82=C5=82=E0=82=B2=97=98=97p=92=\r\n=B8=82=AF=82=DC=82=B7=81B\r\n\t=81=A6=82=B2=97=98=97p=82=C5=82=AB=82=C8=82=A2=92[=96=96=82=E0=82=B2=82=B4=\r\n=82=A2=82=DC=82=B7=81B\r\n\r\n=81=A1=91=BD=90=94=82=CC=83C=83x=83=93=83g\r\n\r\n=81E=83T=83C=83g=93=E0=82=CC=83g=83b=83v=83y=81[=83W=82=F0=8C=A9=82=C4=95=AA=\r\n=82=A9=82=E9=82=E6=82=A4=82=C9=81A=83I=83t=89=EF=82=C8=82=C7=82=E0=82=A0=82=\r\n=E8=83=81=81[=83=8B=82=C5=82=CD=91=CA=96=DA=82=BE=82=C1=82=BD=81A\r\n=95s=88=C0=82=C6=8Ev=82=A4=95=FB=82=C5=82=E0=8EQ=89=C1=82=B5=82=C4=82=A2=82=\r\n=BD=82=BE=82=AF=82=EA=82=CE=81A=91f=93G=82=C8=91=8A=8E=E8=82=AA=8C=A9=82=C2=\r\n=82=A9=82=E9=82=A9=82=C6=8Ev=82=A2=82=DC=82=B7=81B\r\n\r\n\r\n=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=\r\n=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96=\r\n=81=96=81=96=81=96=81=96=81=96=81=96=81=96=81=96\r\n\r\n=81=A5=82=B2=93o=98^=95=FB=96@=82=E0=8A=C8=92P=82=C5=82=B7=81B\r\n=91S=82=C4=82=CC=8B@=94\\=82=F0=82=B2=97=98=97p=92=B8=82=AD=88=D7=82=C9=90=E6=\r\n=82=B8=93o=98^=82=F0=82=B7=82=E9=95K=97v=82=AA=8C=E4=8D=C0=82=A2=82=DC=82=B7=\r\n=81B\r\n=96=DC=98_=93o=98^=82=F0=82=B7=82=E9=82=CC=82=CD=81A=96=B3=97=BF=82=C5=82=B2=\r\n=97=98=97p=92=B8=82=AD=8E=96=82=AA=82=C5=82=AB=82=DC=82=B7=81B\r\n\r\n=81y=81@D-LOVE=83T=83C=83g=89=E6=96=CA=81Fhttp://www.bizworkss.com/dlove=81=\r\n@=81z\r\n=8F=E3=8BL=82=CCURL=82=A9=82=E7=83T=83C=83g=82=C9=82=A8=93=FC=82=E8=82=C9=82=\r\n=C8=82=E8=81A\r\n\r\n=81u=8A=C8=92P=82=B2=97=98=97p=93o=98^=81v=82=CC=83t=83H=81[=83=80=93=E0=82=\r\n=C9=8BL=93=FC=82=B5=82=C4=82=A2=82=BD=82=BE=82=AD=82=BE=82=AF=82=C5\r\n=93o=98^=82=F0=82=B5=82=C4=82=A2=82=BD=82=BE=82=AD=8E=96=82=AA=82=C5=82=AB=\r\n=82=DC=82=B7=81B\r\n\r\n=90=A5=94=F1=88=EA=93x=82=B2=97=98=97p=82=C9=82=C8=82=C1=82=C4=82=DD=82=C4=\r\n=89=BA=82=B3=82=A2=81B\r\n\r\n\r\n=82=BB=82=EA=82=C5=82=CD=8E=B8=97=E7=92v=82=B5=82=DC=82=B7=81B\r\n\r\n\r\nD-LOVE=89^=89c=83X=83^=83b=83t=89Y=93c\r\n\r\n\r\n\r\n----=_cgXS9SvIcF--\r\n"
  },
  {
    "path": "test/fixtures/testcase1",
    "content": "Return-Path: <william.reid@gmail.com>\r\nX-Original-To: andrew@hijacked.us\r\nDelivered-To: andrew@hijacked.us\r\nReceived: from yx-out-1718.google.com (yx-out-1718.google.com [74.125.44.156])\r\n\tby hijacked.us (Postfix) with ESMTP id 1AC2FB3F2\r\n\tfor <andrew@hijacked.us>; Tue, 26 May 2009 22:31:56 -0400 (EDT)\r\nReceived: by yx-out-1718.google.com with SMTP id 6so1940607yxn.56\r\n        for <andrew@hijacked.us>; Tue, 26 May 2009 19:31:55 -0700 (PDT)\r\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r\n        d=gmail.com; s=gamma;\r\n        h=domainkey-signature:received:received:message-id:from:to:subject\r\n         :date:mime-version:content-type:x-priority:x-msmail-priority\r\n         :x-mailer:x-mimeole;\r\n        bh=XUW/FICa9kkl5vDl+xd8H1WlJdR5PJTID/ior6hnv88=;\r\n        b=Zto7CzBCZNxsb55UmpWlAHxsuUcb8vdv032k7tS7AIyiQmitI+HVUjtvDYWM0zACcu\r\n         6N+V3PkaVklU9dHLkcwfNTAJXpyIFjpjnRKfmotN4Rqp/9DmHF2EQesJT3GHaJ2W3jc8\r\n         bgyp3xizESFRqoJZ/Icecsh0JTS6dwj9oDg4E=\r\nDomainKey-Signature: a=rsa-sha1; c=nofws;\r\n        d=gmail.com; s=gamma;\r\n        h=message-id:from:to:subject:date:mime-version:content-type\r\n         :x-priority:x-msmail-priority:x-mailer:x-mimeole;\r\n        b=lnRANxEGsnST99FgRrwGVFay8hJXegLeAaz56EGkq9IImdvmsQ9wHptJrcSqHNg5CQ\r\n         1aeMjvL6Rx71SSu8lX8bFh9ZWd/qiYHU6TNumrkIoQ9F/NxUzEuSXYsl71tdsFmWo/wg\r\n         6qhadyf2HlYluV2R6tBrhxaH+vLpf+1xJvjp4=\r\nReceived: by 10.100.10.13 with SMTP id 13mr16172888anj.10.1243391515342;\r\n        Tue, 26 May 2009 19:31:55 -0700 (PDT)\r\nReceived: from Descarte ([72.146.47.45])\r\n        by mx.google.com with ESMTPS id 9sm1104726yws.20.2009.05.26.19.31.32\r\n        (version=SSLv3 cipher=RC4-MD5);\r\n        Tue, 26 May 2009 19:31:52 -0700 (PDT)\r\nMessage-ID: <26C3BC4ABC50439980806C85A57D263D@Descarte>\r\nFrom: \"Will Reid\" <william.reid@gmail.com>\r\nTo: <andrew@hijacked.us>\r\nSubject: Fw: Height (from xkcd)\r\nDate: Tue, 26 May 2009 21:31:30 -0500\r\nMIME-Version: 1.0\r\nContent-Type: multipart/mixed;\r\n\tboundary=\"----=_NextPart_000_0298_01C9DE49.558ECA90\"\r\nX-Priority: 3\r\nX-MSMail-Priority: Normal\r\nX-Mailer: Microsoft Windows Mail 6.0.6001.18000\r\nX-MimeOLE: Produced By Microsoft MimeOLE V6.0.6001.18049\r\nStatus: RO\r\nContent-Length: 265920\r\nLines: 3712\r\n\r\nThis is a multi-part message in MIME format.\r\n\r\n------=_NextPart_000_0298_01C9DE49.558ECA90\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"----=_NextPart_001_0299_01C9DE49.558ECA90\"\r\n\r\n\r\n------=_NextPart_001_0299_01C9DE49.558ECA90\r\nContent-Type: text/plain;\r\n\tcharset=\"iso-8859-1\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nThis one's just worth forwarding. :)\r\n\r\n----- Original Message -----=20\r\nFrom: Andrew Sanderson=20\r\nTo: undisclosed-recipients\r\nSent: Tuesday, December 09, 2008 1:32 PM\r\nSubject: Height (from xkcd)\r\n\r\n\r\n\r\n------=_NextPart_001_0299_01C9DE49.558ECA90\r\nContent-Type: text/html;\r\n\tcharset=\"iso-8859-1\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n<HTML><HEAD>\r\n<META http-equiv=3DContent-Type content=3D\"text/html; =\r\ncharset=3Diso-8859-1\">\r\n<META content=3D\"MSHTML 6.00.6001.18226\" name=3DGENERATOR>\r\n<STYLE></STYLE>\r\n</HEAD>\r\n<BODY text=3D#000066 bgColor=3D#ffffff>\r\n<DIV><FONT face=3DArial color=3D#000000 size=3D2>This one's just worth =\r\nforwarding.=20\r\n:)</FONT></DIV>\r\n<DIV>&nbsp;</DIV>\r\n<DIV style=3D\"FONT: 10pt arial\">----- Original Message -----=20\r\n<DIV style=3D\"BACKGROUND: #e4e4e4; font-color: black\"><B>From:</B> <A=20\r\ntitle=3Da.m.sanderson@gmail.com =\r\nhref=3D\"mailto:a.m.sanderson@gmail.com\">Andrew=20\r\nSanderson</A> </DIV>\r\n<DIV><B>To:</B> undisclosed-recipients</DIV>\r\n<DIV><B>Sent:</B> Tuesday, December 09, 2008 1:32 PM</DIV>\r\n<DIV><B>Subject:</B> Height (from xkcd)</DIV></DIV>\r\n<DIV><BR></DIV><BR></BODY></HTML>\r\n\r\n------=_NextPart_001_0299_01C9DE49.558ECA90--\r\n\r\n------=_NextPart_000_0298_01C9DE49.558ECA90\r\nContent-Type: message/rfc822;\r\n\tname=\"Height (from xkcd).eml\"\r\nContent-Transfer-Encoding: 7bit\r\nContent-Disposition: attachment;\r\n\tfilename=\"Height (from xkcd).eml\"\r\n\r\nReturn-Path: <a.m.sanderson@gmail.com>\r\nReceived: from ?192.168.1.101? (c-98-193-248-149.hsd1.tn.comcast.net [98.193.248.149])\r\n        by mx.google.com with ESMTPS id d12sm444639and.42.2008.12.09.10.31.33\r\n        (version=TLSv1/SSLv3 cipher=RC4-MD5);\r\n        Tue, 09 Dec 2008 10:31:36 -0800 (PST)\r\nMessage-ID: <493EB988.3080702@gmail.com>\r\nDate: Tue, 09 Dec 2008 12:31:36 -0600\r\nFrom: Andrew Sanderson <a.m.sanderson@gmail.com>\r\nUser-Agent: Thunderbird 2.0.0.18 (Windows/20081105)\r\nMIME-Version: 1.0\r\nTo: undisclosed-recipients:;\r\nSubject: Height (from xkcd)\r\nContent-Type: multipart/alternative;\r\n boundary=\"------------020405070809020207070303\"\r\n\r\nThis is a multi-part message in MIME format.\r\n--------------020405070809020207070303\r\nContent-Type: text/plain; charset=ISO-8859-1; format=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\n\r\n\r\n*from xkcd <http://xkcd.com>*\r\n\r\n--------------020405070809020207070303\r\nContent-Type: multipart/related;\r\n boundary=\"------------080002000700090108040309\"\r\n\r\n\r\n--------------080002000700090108040309\r\nContent-Type: text/html; charset=ISO-8859-1\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n<html>\r\n<head>\r\n</head>\r\n<body alink=\"#ee0000\" bgcolor=\"#000000\" link=\"#0000ee\" text=\"#000066\"\r\n vlink=\"#551a8b\">\r\n<div align=\"center\"><img src=\"cid:part1.03050108.02070304@gmail.com\"\r\n alt=\"\"><br>\r\n<br>\r\n<b><font color=\"#ffff00\">from <a href=\"http://xkcd.com\">xkcd</a></font></b><br>\r\n</div>\r\n</body>\r\n</html>\r\n\r\n--------------080002000700090108040309\r\nContent-Type: image/jpeg;\r\n name=\"moz-screenshot-1.jpg\"\r\nContent-Transfer-Encoding: base64\r\nContent-ID: <part1.03050108.02070304@gmail.com>\r\nContent-Disposition: inline;\r\n filename=\"moz-screenshot-1.jpg\"\r\n\r\n/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9\r\nPDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhC\r\nY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAAR\r\nCApXApYDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA\r\nAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK\r\nFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWG\r\nh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl\r\n5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA\r\nAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYk\r\nNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE\r\nhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk\r\n5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD0CiiigAooooAKKKKACiiigAooooAKKKKA\r\nCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo\r\nooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA\r\nCiiigAooooAKKKKACiiigAqOeeG3j8yeVIkH8TsFH5mud8d3Yg0JxDqH2a6VlZVSXa7joRgc\r\nnjn8K8qZ7i6k+ZpZnPPJLGgD3W1u7e9h861mSaMkjehyMipq838HanqunMNGTTx5sjGdftDm\r\nM7SBnAI56Z/OvSKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo\r\nooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA\r\nCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo\r\nooAKKKKACiis7XNZttE097q4IJ6Rxg8u3oKAMHxnY2kuoaQXt4w9zeIkspUZKj+En8f0rqoL\r\naC2XbbwRxL6IgUfpXmSW3iHxda3OorOxWKUeVAG2qSP7vYEcc+9a2h+J9dvA1g0Vl9siO0m5\r\nkMbfUr3/AAoA2NeRW8U6AY/+PjfJkjrsC85/z610lZWlaO9pcyXt7cm7vpRtMhXCov8AdUdh\r\nWrQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRSUALRSUtABRRRQAUUUUAFFF\r\nFABRRRQAVU1K2nu7Noba7e0kJGJUUMR7YNW6KAOIi0+9m1u/sbnxBqCw2kSSF1fbnIyfpiod\r\nM1bXrXR01YsLjTI32mKQEytHnBk3euf84rTSGS81zxPHErK728cKEjAJ8s9/xFVtN1hm0CLR\r\nILCY6msX2doZIyEXjBZj0296AJbm91bVvEP2PS9RS1szarcpIsQckHHXPv8AyrT8O6heXEt9\r\nYaiUe6sZFVpEGBIrDIOOxrB0zwyj6td2Us94kdrBCglhcoHOCWH5nOO1dVpWkWmkROlqrFpD\r\nmSSRtzufc0AReINYXRrESLGZriVhHBCOrsawpda8TabOl3q1hANPQATeRyVDHr1JyPyq74qV\r\n7e/0nVHjaS0spWM4UZKBgAGx6Cl1bVbfWLQ6XpEyXU12NjtH8ywxn7zN6cdB1zQBmDUNU1PV\r\nL9Y9fttPtLeQLGdiEsp5B59veum0ixubKKQXeoS30kj7t7jaFGOgA4Fcz4a8PaZd3epy3Vn5\r\npt7toYjITwqgAcdDXa0AZfiHWl0WzSQQtPcTOI4Yl6uxrITVte03ULNtbS2Fpev5eIv+WDHp\r\nk/8A66m8TSJa69od5dnbZxSSB3I+VGKjaT+NGt3Vvr6xaTp8i3PmSI88sR3LCgOc7um44wBQ\r\n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\r\njAm0t+PWufJLEkkknqTQB3niG70Ow8TS3zLePqMJU+UhCxu20YOeuMYzWzda9YxapHod7ayv\r\nJcKqScjyyZME5H49a8qJJOSST61NJeXMt0LqSeR51IIkZiWBHTn2xQB6DY3NjomlW8OoQh1g\r\nvpreKdlDGHk4bBqF9d13StUlsLuE6rDOd0ckIKsyN02len+ea4e41G8uoPJnuHkj8wykMern\r\nqasW+v6rbWIsoL6WK3GcKpxjPPB60AdjLZabpthrCXhu57Oe6jQ+Ud0isF3EE+xPWsHQP7KT\r\nxrZ/ZWm+ybvkNyAGD7TjOPfFZum+IdV0tGjs7x40ZtxUgMCfXkGnan4i1DVYBFetE4DBgwiV\r\nWB+oFADNZGp22pXUeoNMs0jfvNxOJADkfUelT6Yvh37IG1N9Q+0AnKQBdpHbBNCeKdWFmbWW\r\ndZ4tu1fPjVyv0JGaxqAOmMPg2TkXOqQ+xVT/AEqP7N4TT5jf6jKAfuLEoJ/E1ztFAHVae/hJ\r\nr2AJFqiSCVQhLIQTngmvVq8I0z/kJ2n/AF2T/wBCFe70AFFFFABRRRQAUUUUAFFFFABRRRQA\r\nUUUUAFFFFABWT4p/5FnUf+uDfyrWrJ8U/wDIs6j/ANcG/lQB4vJG0ZAYdRkEdDTaKKACiiig\r\nAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKK\r\nKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiig\r\nAooooAKKKKACiiigAooooAs6Z/yE7T/rsn/oQr3evCNM/wCQnaf9dk/9CFe70AFFFFABRRRQ\r\nAUUUUAFFFFABRRRQAUUUUAFFFFABWT4p/wCRZ1H/AK4N/KtasnxT/wAizqP/AFwb+VAHitFF\r\nFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQA\r\nUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFPjhlmJEUbvtGTtUnA9aAGUUU+KGWZisM\r\nbyEDJCqTQAyilZWRirKVI6gjFSwWs9ysrQRNIIUMkhUZ2qO5oAhopwRmVmVSVX7xA4H1q5Ho\r\n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\r\nrsn/AKEK93rwjTP+Qnaf9dk/9CFe70AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWT4\r\np/5FnUf+uDfyrWrJ8U/8izqP/XBv5UAeK0UUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFF\r\nFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQ\r\nAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBZ0z/kJ2\r\nn/XZP/QhXu9eEaZ/yE7T/rsn/oQr3egAooooAKKKKACiiigAooooAKKKKACiiigAooooAKyf\r\nFP8AyLOo/wDXBv5VrVk+Kf8AkWdR/wCuDfyoA8VooooAKKKKACiiigAooooAKKKKACiiigAo\r\noooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACilQqHUuu5QeRnGRXd3Pnpc6dZeGbS0\r\ntTc2guf3ioznOeCzZz0/nQBwdFdpqVo99BBpmpG0/t55QI2iABVe4kIGPpiue0iztn16Ow1E\r\nPseQwkxtyrE4B+maAKEME1w22CKSVvRFJP6UksUkL7Jo3jcfwupBrttLtdVXw9e6bpk/lXdp\r\nqBVmVxHvXBGM/UVNDHeNaRWviyFZne6ijtVkYGQ5bD8g524oA4Ciuml0a20W5mu9XjbyBK4t\r\nbTOGnAbgk9l9+9U7a1tdUstZvDH5E8IWaKOPhFUtgrj8RQBi0V1um6fDpnh2HVxp/wDad1cM\r\nQisheOAA4ywHU/Wuav5zc3kkxt4rcseYol2qv0HagCvRRRQAUUUUAFFFFABRRRQAUUUUAFFF\r\nFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAWdM/wCQnaf9dk/9CFe714Rpn/IT\r\ntP8Arsn/AKEK93oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACsnxT/yLOo/9cG/lWtW\r\nT4p/5FnUf+uDfyoA8VooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK\r\nKKKACiiigAooooAKKKKACux1bSp9Rg0mXTru0eS3so42UXKq6sMnuR61x1FAHbtqcmlWds2t\r\nXEN5fw3KPAI3EkkcYPz7mHqOgJqikuiaZq8mrJe/bjvaW3tkjZSGPI3k9MZ7Vy1FAGp/a+/S\r\nb62mR3nurhZzJnABGc/zqDSrxbXWLO7uS7pDKrt3OAc8VSooA6iLxNFqMs9nrivPYTyM0ch5\r\nkt8ngg+g9P8A9VQaQ9jZ3mr2El4jW89s8UVxghSQQVP6Vz1FAGx4cu3huHi/tiXTEZSVZQSh\r\nfsGA/nV/xLqUFxp0VtNeRalfrJuN1FFsCpj7uf4uea5iigAooooAKKKKACiiigAooooAKKKK\r\nACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKALOmf8hO0/67J/6EK93rwjTP\r\n+Qnaf9dk/wDQhXu9ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVk+Kf+RZ1H/rg38q1\r\nqyfFP/Is6j/1wb+VAHitFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFA\r\nBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUU\r\nUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAWdM/5Cdp/12T/ANCFe714\r\nRpn/ACE7T/rsn/oQr3egAooooAKKKKACiiigAooooAKKKKACiiigAooooAKyfFP/ACLOo/8A\r\nXBv5VrVk+Kf+RZ1H/rg38qAPFaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo\r\nAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi\r\niigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAs6Z/wAhO0/67J/6\r\nEK93rwjTP+Qnaf8AXZP/AEIV7vQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFZPin/k\r\nWdR/64N/KtasnxT/AMizqP8A1wb+VAHitFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRR\r\nRQAUUUUAFFFFAF3StJvdYuvs9jEXYcsTwqj1Jq1P4a1SHVI9OEAknkXchjYFWXuc+n1rWsnm\r\n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\r\nM8zuAw+8pPQj6Vpa5rel3WhLaabbPbyT3P2ieM/dRtuML7GgDmKKKKACiiigAooooAKKKKAC\r\niiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAs6Z/yE7T/rsn/oQr3evCNM/wCQnaf9\r\ndk/9CFe70AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABWT4p/wCRZ1H/AK4N/KtasnxT\r\n/wAizqP/AFwb+VAHitFFFABRRRQAUUUUAamlaydPgltpbO2vLeRg5jmTOGHcEc1WvL+S5mmZ\r\nES2hlIzBD8qcdOO/1qpRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUU\r\nUUAFFFFABRRRQAUUUUAFFFFABmiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKK\r\nACiiigAooooAKKKKACiiigAooooAKKKKALOmf8hO0/67J/6EK93rwjTP+Qnaf9dk/wDQhXu9\r\nABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVk+Kf+RZ1H/rg38q1qyfFP/Is6j/1wb+V\r\nAHitFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFA\r\nBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUU\r\nUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAWdM/5Cdp/12T/ANCFe714Rpn/ACE7T/rsn/oQ\r\nr3egAooooAKKKKACiiigAooooAKKKKACiiigAooooAKyfFP/ACLOo/8AXBv5VrVk+Kf+RZ1H\r\n/rg38qAPFaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo\r\nAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi\r\niigAooooAKKKKACiiigAooooAKKKKACiiigAooooAs6Z/wAhO0/67J/6EK93rwjTP+Qnaf8A\r\nXZP/AEIV7vQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFZPin/kWdR/64N/KtasnxT/\r\n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\r\nUAFFFFABRRRQAUUUUAFFFFABWT4p/wCRZ1H/AK4N/KtasnxT/wAizqP/AFwb+VAHitFFFABR\r\nRRQAUUUUAFFFFABUkEz288c0eA8bBlyMjIOelR0UAbGoeKNZ1FDHcXziM9UjwgP1x1rHoooA\r\nKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACii\r\nigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA\r\ns6Z/yE7T/rsn/oQr3evCNM/5Cdp/12T/ANCFe70AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUA\r\nFFFFABWT4p/5FnUf+uDfyrWrJ8U/8izqP/XBv5UAeK0UUUAFFFFABRRRQAUUUUAFFFFABRRR\r\nQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAF\r\nFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRR\r\nQBZ0z/kJ2n/XZP8A0IV7vXhGmf8AITtP+uyf+hCvd6ACiiigAooooAKKKKACiiigAooooAKK\r\nKKACiiigArJ8U/8AIs6j/wBcG/lWtWT4p/5FnUf+uDfyoA8VooooAKKKKACiiigAooooAKKK\r\nKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigA\r\nooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK\r\nKACiiigCzpn/ACE7T/rsn/oQr3evCNM/5Cdp/wBdk/8AQhXu9ABRRRQAUUUUAFFFFABRRRQA\r\nUUUUAFFFFABRRRQAVk+Kf+RZ1H/rg38q1qyfFP8AyLOo/wDXBv5UAeK0UUUAFFFFABRRRQAU\r\nUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV0Vl4YVLNL/XLxdPtXGY1I3SSfRag8I2MF9rsYuwD\r\nbQK00uem1R39s4qlrOqT6vqUt3OxO44ReyL2AoA3bPSfDOqXKWNhd6kLlydrvGpU4Geg5rG1\r\n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\r\nCj/9+B/8VR/wrOL/AKCj/wDfgf8AxVd7RQBwX/Cs4v8AoKP/AN+B/wDFUf8ACs4v+go//fgf\r\n/FV3tFAHBf8ACs4v+go//fgf/FUf8Kzi/wCgo/8A34H/AMVXe0UAcF/wrOL/AKCj/wDfgf8A\r\nxVH/AArOL/oKP/34H/xVd7RQBwX/AArOL/oKP/34H/xVH/Cs4v8AoKP/AN+B/wDFV3tFAHBf\r\n8Kzi/wCgo/8A34H/AMVR/wAKzi/6Cj/9+B/8VXe0UAcF/wAKzi/6Cj/9+B/8VR/wrOL/AKCj\r\n/wDfgf8AxVd7RQBwX/Cs4v8AoKP/AN+B/wDFUf8ACs4v+go//fgf/FV3tFAHBf8ACs4v+go/\r\n/fgf/FUf8Kzi/wCgo/8A34H/AMVXe0UAcF/wrOL/AKCj/wDfgf8AxVH/AArOL/oKP/34H/xV\r\nd7RQBw1t8OY7e5imGpu3luHx5I5wc+tdzRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUU\r\nUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAB\r\nRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUU\r\nUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAf/2Q==\r\n--------------080002000700090108040309--\r\n\r\n--------------020405070809020207070303--\r\n\r\n------=_NextPart_000_0298_01C9DE49.558ECA90--\r\n\r\n"
  },
  {
    "path": "test/fixtures/testcase2",
    "content": "Return-Path: <william.reid@gmail.com>\r\nX-Original-To: andrew@hijacked.us\r\nDelivered-To: andrew@hijacked.us\r\nReceived: from yw-out-1718.google.com (yw-out-1718.google.com [74.125.46.153])\r\n\tby hijacked.us (Postfix) with ESMTP id E08DCB3F2\r\n\tfor <andrew@hijacked.us>; Tue, 26 May 2009 22:32:13 -0400 (EDT)\r\nReceived: by yw-out-1718.google.com with SMTP id 9so1941843ywk.56\r\n        for <andrew@hijacked.us>; Tue, 26 May 2009 19:32:12 -0700 (PDT)\r\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r\n        d=gmail.com; s=gamma;\r\n        h=domainkey-signature:received:received:message-id:from:to:subject\r\n         :date:mime-version:content-type:x-priority:x-msmail-priority\r\n         :x-mailer:x-mimeole;\r\n        bh=cmUNyG1nd+ULM9B/aXEtmoxYYnjv9jtHzBacpI4wtng=;\r\n        b=dji9x+fIR2sTUnvL5WbzB97s1S5xntcYn51DgS4RB7KDusMukSDgg3J4Mgy/ei3bch\r\n         BHJXl46FtaAns/EYxBOylXoP81CZcJIs7UNWAJoE6we8mghGzhB0ZXY5Zkerx+xBc3rn\r\n         gvCu9lWk/smWPVaoKlUXp8Hh/u2pKh0mftcj4=\r\nDomainKey-Signature: a=rsa-sha1; c=nofws;\r\n        d=gmail.com; s=gamma;\r\n        h=message-id:from:to:subject:date:mime-version:content-type\r\n         :x-priority:x-msmail-priority:x-mailer:x-mimeole;\r\n        b=beYObQbQkvOCWydf2r2U/eOdFVDXD/eytcmV+77Ne1PBWH5o6yRowtRxYmVvgyfln2\r\n         fuDmOj2SvU31OMJ7FmN/Q1kqju3OZaxJrop9DztTNfzmeTTopkx0HFo1HiOTMtOselc6\r\n         BxhW8WDDOvPE21Aig8+5Z2B4FoEc88/8uRDIY=\r\nReceived: by 10.151.130.1 with SMTP id h1mr18063403ybn.216.1243391532852;\r\n        Tue, 26 May 2009 19:32:12 -0700 (PDT)\r\nReceived: from Descarte ([72.146.47.45])\r\n        by mx.google.com with ESMTPS id 6sm1765306ywp.54.2009.05.26.19.32.10\r\n        (version=SSLv3 cipher=RC4-MD5);\r\n        Tue, 26 May 2009 19:32:12 -0700 (PDT)\r\nMessage-ID: <9B86680719474DC2A647FB86284656F3@Descarte>\r\nFrom: \"Will Reid\" <william.reid@gmail.com>\r\nTo: <andrew@hijacked.us>\r\nSubject: Fw: Returned mail: see transcript for details\r\nDate: Tue, 26 May 2009 21:31:51 -0500\r\nMIME-Version: 1.0\r\nContent-Type: multipart/mixed;\r\n\tboundary=\"----=_NextPart_000_02B5_01C9DE49.621B3960\"\r\nX-Priority: 3\r\nX-MSMail-Priority: Normal\r\nX-Mailer: Microsoft Windows Mail 6.0.6001.18000\r\nX-MimeOLE: Produced By Microsoft MimeOLE V6.0.6001.18049\r\nStatus: RO\r\nContent-Length: 6349\r\nLines: 159\r\n\r\nThis is a multi-part message in MIME format.\r\n\r\n------=_NextPart_000_02B5_01C9DE49.621B3960\r\nContent-Type: text/plain;\r\n\tformat=flowed;\r\n\tcharset=\"iso-8859-1\";\r\n\treply-type=original\r\nContent-Transfer-Encoding: 7bit\r\n\r\n\r\n----- Original Message ----- \r\nFrom: \"Mail Delivery Subsystem\" \r\n<MAILER-DAEMON@mailgate03.csm.vanderbilt.edu>\r\nTo: <william.reid@gmail.com>\r\nSent: Friday, January 16, 2009 12:14 AM\r\nSubject: Returned mail: see transcript for details\r\n\r\n\r\n> The original message was received at Thu, 15 Jan 2009 23:14:52 -0600\r\n> from mail-qy0-f21.google.com [209.85.221.21]\r\n>\r\n>   ----- The following addresses had permanent fatal errors -----\r\n> <Chris.c.stowers@vanderbilt.edu>\r\n>    (reason: 550 5.1.1 <Chris.c.stowers@vanderbilt.edu>... Unregistered \r\n> address - Chris.c.stowers@vanderbilt.edu)\r\n>\r\n>   ----- Transcript of session follows -----\r\n> ... while talking to smtp05.smtp.vanderbilt.edu.:\r\n>>>> DATA\r\n> <<< 550 5.1.1 <Chris.c.stowers@vanderbilt.edu>... Unregistered address - \r\n> Chris.c.stowers@vanderbilt.edu\r\n> 550 5.1.1 <Chris.c.stowers@vanderbilt.edu>... User unknown\r\n> <<< 503 5.0.0 Need RCPT (recipient)\r\n> \r\n\r\n------=_NextPart_000_02B5_01C9DE49.621B3960\r\nContent-Type: application/octet-stream;\r\n\tname=\"ATT00687.dat\"\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Disposition: attachment;\r\n\tfilename=\"ATT00687.dat\"\r\n\r\nReporting-MTA: dns; mailgate03.csm.vanderbilt.edu\r\nReceived-From-MTA: DNS; mail-qy0-f21.google.com\r\nArrival-Date: Thu, 15 Jan 2009 23:14:52 -0600\r\n\r\nFinal-Recipient: RFC822; Chris.c.stowers@vanderbilt.edu\r\nAction: failed\r\nStatus: 5.1.1\r\nRemote-MTA: DNS; smtp05.smtp.vanderbilt.edu\r\nDiagnostic-Code: SMTP; 550 5.1.1 <Chris.c.stowers@vanderbilt.edu>... =\r\nUnregistered address - Chris.c.stowers@vanderbilt.edu\r\nLast-Attempt-Date: Thu, 15 Jan 2009 23:14:52 -0600\r\n\r\n------=_NextPart_000_02B5_01C9DE49.621B3960\r\nContent-Type: message/rfc822;\r\n\tname=\"T5 Fixtures.eml\"\r\nContent-Transfer-Encoding: 7bit\r\nContent-Disposition: attachment;\r\n\tfilename=\"T5 Fixtures.eml\"\r\n\r\nReturn-Path: <william.reid@gmail.com>\r\nReceived: from mail-qy0-f21.google.com (mail-qy0-f21.google.com [209.85.221.21])\r\n\tby mailgate03.csm.vanderbilt.edu (8.14.1/8.14.1) with ESMTP id n0G5Eq0E016380\r\n\tfor <Chris.c.stowers@vanderbilt.edu>; Thu, 15 Jan 2009 23:14:52 -0600\r\nReceived: by qyk14 with SMTP id 14so1553601qyk.21\r\n        for <Chris.c.stowers@vanderbilt.edu>; Thu, 15 Jan 2009 21:14:51 -0800 (PST)\r\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r\n        d=gmail.com; s=gamma;\r\n        h=domainkey-signature:received:received:message-id:from:to:subject\r\n         :date:mime-version:content-type:x-priority:x-msmail-priority\r\n         :x-mailer:x-mimeole;\r\n        bh=ceXQdWhI5oV67fvCk2fCpRopNM/rB83uG94rzfVSbAo=;\r\n        b=MQO7pjlcUdU94dX2HbmGqBVjieqkLCBQjEi+EXbkB/tNr5MjLPuzkUnFSdkH8I4UMx\r\n         fLE8xbLxtBlJ+NEtHpTw5sftWyqtlryi1s4NUZ6hHkk/76q6K5YM7xRFh+Eh5hLlJvvS\r\n         6xfTZv4zPlMNRJisYMoWuJ0yYfmbC3h8hKzSg=\r\nDomainKey-Signature: a=rsa-sha1; c=nofws;\r\n        d=gmail.com; s=gamma;\r\n        h=message-id:from:to:subject:date:mime-version:content-type\r\n         :x-priority:x-msmail-priority:x-mailer:x-mimeole;\r\n        b=wrlKoTMhb0DHqmVXZUnLI3HbQwunzqCT30zRVqHdvV4pG6hxPjRKR6oT+ZTRsFX8Sz\r\n         dlNV+dCePJ9h1sceEESYJcCebtGc1wsbCo1u8ltoKdPQ8USNfRibl57V8g5GRkXBfOiL\r\n         Gt1uy1TzpXlXeCreD9vpwA39i9CtAXe7Ht6Gw=\r\nReceived: by 10.214.216.17 with SMTP id o17mr3006883qag.120.1232082891836;\r\n        Thu, 15 Jan 2009 21:14:51 -0800 (PST)\r\nReceived: from Descarte ([68.159.157.188])\r\n        by mx.google.com with ESMTPS id 6sm2353329ywc.59.2009.01.15.21.14.50\r\n        (version=SSLv3 cipher=RC4-MD5);\r\n        Thu, 15 Jan 2009 21:14:51 -0800 (PST)\r\nMessage-ID: <9EE3070BB5BA49E1BC5393673B318C9C@Descarte>\r\nFrom: \"Will Reid\" <william.reid@gmail.com>\r\nTo: \"Chris Stowers\" <Chris.c.stowers@vanderbilt.edu>\r\nSubject: T5 Fixtures\r\nDate: Thu, 15 Jan 2009 23:14:41 -0600\r\nMIME-Version: 1.0\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"----=_NextPart_000_0136_01C97767.0B928BA0\"\r\nX-Priority: 3\r\nX-MSMail-Priority: Normal\r\nX-Mailer: Microsoft Windows Mail 6.0.6001.18000\r\nX-MimeOLE: Produced By Microsoft MimeOLE V6.0.6001.18049\r\nX-Proofpoint-Virus-Version: vendor=fsecure engine=1.12.7400:2.4.4,1.2.40,4.0.166 definitions=2009-01-16_01:2009-01-08,2009-01-16,2009-01-16 signatures=0\r\nX-PPS: No, score=0\r\n\r\nThis is a multi-part message in MIME format.\r\n\r\n------=_NextPart_000_0136_01C97767.0B928BA0\r\nContent-Type: text/plain;\r\n\tcharset=\"iso-8859-1\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nYou really should order 4 or 5 of these before they're sold out.  I =\r\ndon't think you'll find this good a deal on T5 fixtures for a while.  If =\r\nyou're really serious about setting up a prop system, this is a chance =\r\nto really save some money getting it started.\r\n\r\nhttp://www.hellolights.com/index.asp?PageAction=3DVIEWPROD&ProdID=3D1717\r\n\r\n$155 shipped with bulbs is cheaper than you can get retro kits.  It =\r\nwould probably be worth buying an extra set of UVL 10k and actinic bulbs =\r\nto compare them to the Tru bulbs.\r\n------=_NextPart_000_0136_01C97767.0B928BA0\r\nContent-Type: text/html;\r\n\tcharset=\"iso-8859-1\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n<HTML><HEAD>\r\n<META http-equiv=3DContent-Type content=3D\"text/html; =\r\ncharset=3Diso-8859-1\">\r\n<META content=3D\"MSHTML 6.00.6001.18183\" name=3DGENERATOR>\r\n<STYLE></STYLE>\r\n</HEAD>\r\n<BODY bgColor=3D#ffffff>\r\n<DIV><FONT face=3DArial size=3D2>You really should order 4 or 5 of these =\r\nbefore=20\r\nthey're sold out.&nbsp; I don't think you'll find this good a deal on T5 =\r\n\r\nfixtures for a while.&nbsp; If you're really serious about setting up a =\r\nprop=20\r\nsystem, this is a chance to really save some money getting it=20\r\nstarted.</FONT></DIV>\r\n<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>\r\n<DIV><FONT face=3DArial size=3D2><A=20\r\nhref=3D\"http://www.hellolights.com/index.asp?PageAction=3DVIEWPROD&amp;Pr=\r\nodID=3D1717\">http://www.hellolights.com/index.asp?PageAction=3DVIEWPROD&a=\r\nmp;ProdID=3D1717</A></FONT></DIV>\r\n<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>\r\n<DIV><FONT face=3DArial size=3D2>$155 shipped with bulbs is cheaper than =\r\nyou can get=20\r\nretro kits.&nbsp; It would probably be worth buying an extra set of UVL =\r\n10k and=20\r\nactinic bulbs to compare them to the Tru =\r\nbulbs.</FONT></DIV></BODY></HTML>\r\n\r\n------=_NextPart_000_0136_01C97767.0B928BA0--\r\n\r\n\r\n------=_NextPart_000_02B5_01C9DE49.621B3960--\r\n\r\n"
  },
  {
    "path": "test/fixtures/text-attachment-only.eml",
    "content": "Message-Id: <772DB62B-59DA-4D17-8E5E-51288FE236EE@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-16--712639856\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: text attachment only\r\nDate: Mon, 1 Jun 2009 14:55:32 -0400\r\n\r\n\r\n--Apple-Mail-16--712639856\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-16--712639856--\r\n"
  },
  {
    "path": "test/fixtures/the-gamut.eml",
    "content": "Message-Id: <D2C3D072-03B7-4FE6-8ABE-60AA95989BCA@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/alternative;\r\n\tboundary=Apple-Mail-28--711949187\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: The gamut\r\nDate: Mon, 1 Jun 2009 15:07:03 -0400\r\n\r\n\r\n--Apple-Mail-28--711949187\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis is rich text.\r\n\r\nThe list is html.\r\n\r\nAttchments:\r\nan email containing an attachment of an email.\r\nan email of only plain text.\r\nan image\r\nan rtf file.\r\n\r\n--Apple-Mail-28--711949187\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-29--711949186\r\n\r\n\r\n--Apple-Mail-29--711949186\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><b>This</b> is <i>rich</i> text.<div><br></div><div>The list is html.</div><div><br></div><div>Attchments:</div><div><ul class=\"MailOutline\"><li>an email containing an attachment of an email.</li><li>an email of only plain text.</li><li>an image</li><li>an rtf file.</li></ul></div><div></div></body></html>\r\n--Apple-Mail-29--711949186\r\nContent-Disposition: attachment;\r\n\tfilename=\"message as attachment.eml\"\r\nContent-Type: message/rfc822;\r\n\tx-mac-hide-extension=yes;\r\n\tx-unix-mode=0666;\r\n\tname=\"message as attachment.eml\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\nMessage-Id: <AF6A2412-AFCD-4E45-96B0-C1B8C896B2A2@openacd.example.com>\r\nFrom: Micah Warren <mwarren@openacd.example.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: multipart/mixed;\r\n\tboundary=Apple-Mail-19--712443629\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: message as attachment\r\nDate: Mon, 1 Jun 2009 14:58:48 -0400\r\n\r\n\r\n--Apple-Mail-19--712443629\r\nContent-Disposition: attachment;\r\n\tfilename=\"Plain text only\"\r\nContent-Type: message/rfc822;\r\n\tx-mac-hide-extension=yes;\r\n\tx-unix-mode=0666;\r\n\tname=\"Plain text only\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\nMessage-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n\r\n--Apple-Mail-19--712443629--\r\n\r\n--Apple-Mail-29--711949186\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><div></div></body></html>\r\n--Apple-Mail-29--711949186\r\nContent-Disposition: attachment;\r\n\tfilename=\"Plain text only.eml\"\r\nContent-Type: message/rfc822;\r\n\tx-mac-hide-extension=yes;\r\n\tx-unix-mode=0666;\r\n\tname=\"Plain text only.eml\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\nMessage-Id: <F5B196D4-10CD-4876-822F-59C5C39D520E@fusedsolutions.com>\r\nFrom: Micah Warren <micahw@fusedsolutions.com>\r\nTo: test@devmicah.fusedsolutions.com\r\nContent-Type: text/plain;\r\n\tcharset=US-ASCII;\r\n\tformat=flowed\r\nContent-Transfer-Encoding: 7bit\r\nX-Smtp-Server: mail.fusedsolutions.com:micahw@fusedsolutions.com\r\nMime-Version: 1.0 (Apple Message framework v935.3)\r\nSubject: Plain text only\r\nDate: Mon, 1 Jun 2009 14:50:15 -0400\r\n\r\nThis message contains only plain text.\r\n\r\n--Apple-Mail-29--711949186\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><div></div></body></html>\r\n--Apple-Mail-29--711949186\r\nContent-Disposition: inline;\r\n\tfilename=chili-pepper.jpg\r\nContent-Type: image/jpeg;\r\n\tx-unix-mode=0644;\r\n\tname=\"chili-pepper.jpg\"\r\nContent-Transfer-Encoding: base64\r\n\r\n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\r\n\r\n--Apple-Mail-29--711949186\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><div></div></body></html>\r\n--Apple-Mail-29--711949186\r\nContent-Disposition: attachment;\r\n\tfilename=test.rtf\r\nContent-Type: text/rtf;\r\n\tx-unix-mode=0644;\r\n\tname=\"test.rtf\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{\\rtf1\\ansi\\ansicpg1252\\cocoartf949\\cocoasubrtf460\r\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}\r\n{\\colortbl;\\red255\\green255\\blue255;}\r\n\\margl1440\\margr1440\\vieww9000\\viewh8400\\viewkind0\r\n\\pard\\tx720\\tx1440\\tx2160\\tx2880\\tx3600\\tx4320\\tx5040\\tx5760\\tx6480\\tx7200\\tx7920\\tx8640\\ql\\qnatural\\pardirnatural\r\n\r\n\\f0\\fs24 \\cf0 This is a basic rtf file.}\r\n--Apple-Mail-29--711949186\r\nContent-Type: text/html;\r\n\tcharset=US-ASCII\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<html><body style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; \"><div></div></body></html>\r\n--Apple-Mail-29--711949186--\r\n\r\n--Apple-Mail-28--711949187--\r\n"
  },
  {
    "path": "test/fixtures/unicode-body.eml",
    "content": "Return-Path: <mwarren@spicecsm.com>\r\nReceived: from devmicah.fusedsolutions.com (localhost.localdomain [127.0.0.1])\r\n    by mail.fusedsolutions.com (Scalix SMTP Relay 11.4.2.12068)\r\n    via ESMTP; Tue, 06 Oct 2009 15:04:57 -0400 (EDT)\r\nDate: Tue, 6 Oct 2009 15:04:56 -0400\r\nFrom: Micah Warren <mwarren@spicecsm.com>\r\nTo: Micah Warren(SpiceCSM) <mwarren@spicecsm.com>\r\nMessage-ID: <B43C8DB4-76AD-44B9-9BF0-F59F65AECD39@spicecsm.com>\r\nSubject: unicode body\r\nX-Mailer: Apple Mail (2.936)\r\nMime-Version: 1.0 (Apple Message framework v936)\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"Apple-Mail-1--476693635\"\r\n\r\n--Apple-Mail-1--476693635\r\nContent-Type: text/plain;\r\n\tcharset=\"UTF-8\";\r\n\tformat=\"flowed\"\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Disposition: inline\r\n\r\n=E2=91=A0=E2=93=AB=E2=85=93=E3=8F=A8=E2=99=B3=F0=9D=84=9E=CE=BB\r\n\r\nCharaacters are:\r\n\r\n2460 (circled digit one)\r\n24EB (negative circled number eleven)\r\n2153 (vulgar fraction one third)\r\n33E8 (ideographic telegraph symbol for day nine)\r\n2673 (recycling symbol for type-1 plastics)\r\n1D11E(D834+DD1E) (Musical Symbol G clef)\r\n03BB (greek small letter lamda)\r\n--Apple-Mail-1--476693635\r\nContent-Type: text/html;\r\n\tcharset=\"UTF-8\"\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Disposition: inline\r\n\r\n<html><body style=3D\"word-wrap: break-word; -webkit-nbsp-mode: space; -we=\r\nbkit-line-break: after-white-space; \"><p style=3D\"margin: 0.0px 0.0px 1.0=\r\npx 56.0px; text-indent: -56.0px; font: 12.0px Hiragino Kaku Gothic ProN\">=\r\n<b>=E2=91=A0=E2=93=AB=E2=85=93</b><span style=3D\"font: 12.0px Arial Unico=\r\nde MS\">=E3=8F=A8</span><b>=E2=99=B3</b><span style=3D\"font: 12.0px Apple S=\r\nymbols\">=F0=9D=84=9E</span><span style=3D\"font: 12.0px Helvetica\"><b>=CE=BB=\r\n</b></span></p><p style=3D\"margin: 0.0px 0.0px 1.0px 56.0px; text-indent:=\r\n -56.0px; font: 12.0px Hiragino Kaku Gothic ProN\"><font class=3D\"Apple-st=\r\nyle-span\" face=3D\"Helvetica\"><b><br></b></font></p>Charaacters are:<br><b=\r\nr>2460 (circled digit one)<br>24EB (negative circled number eleven)<br>21=\r\n53 (vulgar fraction one third)<br>33E8 (ideographic telegraph symbol for d=\r\nay nine)<br>2673 (recycling symbol for type-1 plastics)<br>1D11E(D834+DD1=\r\nE) (Musical Symbol G clef)<br>03BB (greek small letter lamda)</body></htm=\r\nl>\r\n--Apple-Mail-1--476693635--\r\n"
  },
  {
    "path": "test/fixtures/unicode-subject.eml",
    "content": "Return-Path: <mwarren@spicecsm.com>\r\nReceived: from devmicah.fusedsolutions.com (localhost.localdomain [127.0.0.1])\r\n    by mail.fusedsolutions.com (Scalix SMTP Relay 11.4.2.12068)\r\n    via ESMTP; Tue, 06 Oct 2009 15:02:54 -0400 (EDT)\r\nDate: Tue, 6 Oct 2009 15:02:53 -0400\r\nFrom: Micah Warren <mwarren@spicecsm.com>\r\nTo: Micah Warren(SpiceCSM) <mwarren@spicecsm.com>\r\nMessage-ID: <DB506DFF-C267-4193-A5B7-473AA2C62A02@spicecsm.com>\r\nSubject: =?UTF-8?Q?=E2=91=A0=E2=93=AB=E2=85=93=E3=8F=A8=E2=99=B3=F0=9D=84=9E=CE=BB?=\r\nX-Mailer: Apple Mail (2.936)\r\nMime-Version: 1.0 (Apple Message framework v936)\r\nContent-Type: text/plain;\r\n\tcharset=\"US-ASCII\";\r\n\tformat=\"flowed\"\r\nContent-Disposition: inline\r\n\r\nThe body is plain text, the actual test is the subject line.\r\n\r\nCharaacters are:\r\n\r\n2460 (circled digit one)\r\n24EB (negative circled number eleven)\r\n2153 (vulgar fraction one third)\r\n33E8 (ideographic telegraph symbol for day nine)\r\n2673 (recycling symbol for type-1 plastics)\r\n1D11E(D834+DD1E) (Musical Symbol G clef)\r\n03BB (greek small letter lamda)\r\n"
  },
  {
    "path": "test/fixtures/utf-attachment-name.eml",
    "content": "MIME-Version: 1.0\r\nReceived: by 10.49.107.74 with HTTP; Sat, 4 May 2013 10:02:04 -0700 (PDT)\r\nDate: Sat, 4 May 2013 21:02:04 +0400\r\nDelivered-To: seriy.pr@example.com\r\nMessage-ID: <CAMZoz@mail.example.com>\r\nSubject: Hello\r\nFrom: =?KOI8-R?B?88XSx8XKIPDSz8jP0s/X?= <seriy.pr@example.com>\r\nTo: aonfmqcpw@example.com\r\nContent-Type: multipart/mixed; boundary=047d7b672bf44fac7f04dbe76d1f\r\n\r\n--047d7b672bf44fac7f04dbe76d1f\r\nContent-Type: text/plain; charset=ISO-8859-1\r\n\r\nHello\r\n\r\n--047d7b672bf44fac7f04dbe76d1f\r\nContent-Type: text/plain; charset=US-ASCII; name=\"=?KOI8-R?B?1MXT1M/X2cogxsHKzC50eHQ=?=\"\r\nContent-Disposition: attachment; filename=\"=?KOI8-R?B?1MXT1M/X2cogxsHKzC4=?=\r\n    =?KOI8-R?B?dHh0?=\"\r\nContent-Transfer-Encoding: base64\r\nX-Attachment-Id: f_hgb1h6xc0\r\n\r\ncXdlcXdlCg==\r\n--047d7b672bf44fac7f04dbe76d1f--"
  },
  {
    "path": "test/gen_smtp_server_test.erl",
    "content": "-module(gen_smtp_server_test).\n\n-compile([export_all, nowarn_export_all]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\ninvalid_lmtp_port_test_() ->\n    {\"gen_smtp_server should prevent starting LMTP on port 25 (RFC2023, section 5)\", fun() ->\n        Options = [{port, 25}, {sessionoptions, [{protocol, lmtp}]}],\n        [\n            ?_assertMatch(\n                {error, invalid_lmtp_port},\n                gen_smtp_server:start(gen_smtp_server, Options)\n            ),\n            ?_assertError(\n                invalid_lmtp_port,\n                gen_smtp_server:child_spec(\"LMTP Server\", gen_smtp_server, Options)\n            )\n        ]\n    end}.\n"
  },
  {
    "path": "test/gen_smtp_util_test.erl",
    "content": "%% coding: utf-8\n-module(gen_smtp_util_test).\n\n-compile([export_all, nowarn_export_all]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\ntest_test() ->\n    smtp_util:parse_rfc822_addresses(\"foo bar\").\n\nparse_rfc822_addresses_test_() ->\n    F = fun smtp_util:parse_rfc822_addresses/1,\n    [\n        {\"Empty address list parse_rfc2822_addresses_test\", fun() ->\n            ?assertEqual({ok, []}, F(<<>>)),\n            ?assertEqual({ok, []}, F(<<\"   \">>)),\n            ?assertEqual({ok, []}, F(<<\" \\r\\n\\t  \">>)),\n            ?assertEqual({ok, []}, F(<<\"\\n\">>))\n        end},\n        {\"Group parse_rfc2822_addresses_test\", fun() ->\n            %% XXX: this is incorrect...\n            ?assertEqual(\n                {ok, [{undefined, \"undisclosed-recipients:;\"}]},\n                F(<<\"undisclosed-recipients:;\">>)\n            )\n        end},\n        {\"Multiple with comma  parse_rfc2822_addresses_test\", fun() ->\n            ?assertEqual(\n                {ok, [{\"Jan\", \"a,a@a.com\"}, {undefined, \"b@b.com\"}]},\n                F(<<\"Jan <a,a@a.com>,b@b.com\">>)\n            )\n        end}\n        | parse_adresses_t(F)\n    ].\n\nparse_rfc2822_addresses_test_() ->\n    F = fun smtp_util:parse_rfc5322_addresses/1,\n    [\n        {\"Group parse_rfc822_addresses_test\", fun() ->\n            %% rfc5322#section-3.4\n            %% empty group\n            ?assertEqual(\n                {ok, []},\n                F(<<\"undisclosed-recipients:;\">>)\n            ),\n            %% group with recipient list\n            ?assertEqual(\n                {ok, [{undefined, \"a@a.com\"}, {undefined, \"b@b.com\"}]},\n                F(<<\"friends:a@a.com,b@b.com;\">>)\n            )\n        end}\n        | parse_adresses_t(F)\n    ].\n\nparse_adresses_t(F) ->\n    {_, FName} = erlang:fun_info(F, name),\n    FStr = atom_to_list(FName),\n    [\n        {\"Single addresses \" ++ FStr, fun() ->\n            ?assertEqual(\n                {ok, [{undefined, \"john@doe.com\"}]},\n                F(<<\"john@doe.com\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"Fræderik Hølljen\", \"me@example.com\"}]},\n                F(<<\"Fræderik Hølljen <me@example.com>\"/utf8>>)\n            ),\n            ?assertEqual(\n                {ok, [{undefined, \"john@doe.com\"}]},\n                F(<<\"<john@doe.com>\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"John\", \"john@doe.com\"}]},\n                F(<<\"John <john@doe.com>\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"John Doe\", \"john@doe.com\"}]},\n                F(<<\"John Doe <john@doe.com>\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"John Doe\", \"john@doe.com\"}]},\n                F(<<\"\\\"John Doe\\\" <john@doe.com>\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"John \\\"Mighty\\\" Doe\", \"john@doe.com\"}]},\n                F(<<\"\\\"John \\\\\\\"Mighty\\\\\\\" Doe\\\" <john@doe.com>\">>)\n            )\n        end},\n        {\"Multiple addresses \" ++ FStr, fun() ->\n            ?assertEqual(\n                {ok, [{undefined, \"a@a.com\"}, {undefined, \"b@b.com\"}]},\n                F(<<\"a@a.com,b@b.com\">>)\n            ),\n            ?assertEqual(\n                {ok, [{undefined, \"a@a.com\"}, {undefined, \"b@b.com\"}]},\n                F(<<\"<a@a.com>,b@b.com\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"Jan\", \"a@a.com\"}, {undefined, \"b@b.com\"}]},\n                F(<<\"Jan <a@a.com>,b@b.com\">>)\n            ),\n            ?assertEqual(\n                {ok, [{\"Jan\", \"a@a.com\"}, {\"Berend Botje\", \"b@b.com\"}]},\n                F(<<\"Jan <a@a.com>,\\\"Berend Botje\\\" <b@b.com>\">>)\n            )\n        end}\n    ].\n\ncombine_rfc822_addresses_test_() ->\n    [\n        {\"One address\", fun() ->\n            ?assertEqual(\n                <<\"john@doe.com\">>,\n                smtp_util:combine_rfc822_addresses([{undefined, \"john@doe.com\"}])\n            ),\n            ?assertEqual(\n                <<\"John <john@doe.com>\">>,\n                smtp_util:combine_rfc822_addresses([{\"John\", \"john@doe.com\"}])\n            ),\n            ?assertEqual(\n                <<\"\\\"John \\\\\\\"Foo\\\" <john@doe.com>\">>,\n                smtp_util:combine_rfc822_addresses([{\"John \\\"Foo\", \"john@doe.com\"}])\n            )\n        end},\n        {\"Multiple addresses\", fun() ->\n            ?assertEqual(\n                <<\"john@doe.com, foo@bar.com\">>,\n                smtp_util:combine_rfc822_addresses([\n                    {undefined, \"john@doe.com\"}, {undefined, \"foo@bar.com\"}\n                ])\n            ),\n            ?assertEqual(\n                <<\"John <john@doe.com>, foo@bar.com\">>,\n                smtp_util:combine_rfc822_addresses([\n                    {\"John\", \"john@doe.com\"}, {undefined, \"foo@bar.com\"}\n                ])\n            )\n        end}\n    ].\n\nillegal_rfc822_addresses_test_() ->\n    [\n        {\"Nested brackets\", fun() ->\n            ?assertEqual(\n                {error, {0, smtp_rfc822_parse, [\"syntax error before: \", \"\\\">\\\"\"]}},\n                smtp_util:parse_rfc822_addresses(\"a<b<c>>\")\n            )\n        end}\n    ].\n\nrfc822_addresses_roundtrip_test() ->\n    Addr = <<\"Jan <a,a@a.com>, Berend Botje <b@b.com>\">>,\n    {ok, Parsed} = smtp_util:parse_rfc822_addresses(Addr),\n    ?assertEqual(Addr, smtp_util:combine_rfc822_addresses(Parsed)),\n    ok.\n\nrfc2047_utf8_encode_test() ->\n    UnicodeString = unicode:characters_to_binary(\"€ € € € € 1234 € € € € 123 € € € € € 1234€\"),\n    Encoded = <<\n        \"=?UTF-8?B?4oKsIOKCrCDigqwg4oKsIOKCrCAxMjM0IOKCrCDigqwg4oKsIOKCrCAxMjMg?=\\r\\n\"\n        \" =?UTF-8?B?4oKsIOKCrCDigqwg4oKsIOKCrCAxMjM04oKs?=\"\n    >>,\n    ?assertEqual(Encoded, mimemail:rfc2047_utf8_encode(UnicodeString)).\n"
  },
  {
    "path": "test/generate_test_certs.sh",
    "content": "#!/bin/sh\n# https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CERTIFICATE-CREATION\n\nDATADIR=test/fixtures\nCA_SUBJ=\"/CN=gen_smtp CA\"\nSERVER1_SUBJ=\"/CN=epgsql server\"\nset -x\n\n# generate root key\nopenssl genrsa -out ${DATADIR}/root.key 2048\n# generate root cert\nopenssl req -new -x509 -text -days 3650 -key ${DATADIR}/root.key -out ${DATADIR}/root.crt -subj \"$CA_SUBJ\"\n\nfor DOMAIN in \"mx1.example.com\" \"mx2.example.com\"; do\n\tKEY=${DATADIR}/${DOMAIN}-server.key\n\tCSR=${DATADIR}/${DOMAIN}-server.csr\n\tCRT=${DATADIR}/${DOMAIN}-server.crt\n\t# generate server1 key\n\topenssl genrsa -out $KEY 2048\n\t# generate server signature request\n\topenssl req -new -key $KEY -out $CSR -subj \"/CN=${DOMAIN}\"\n\t# create signed server cert\n\topenssl x509 -req -text -days 3650 -in $CSR -CA ${DATADIR}/root.crt -CAkey ${DATADIR}/root.key -CAcreateserial -out $CRT\ndone\n\nrm ${DATADIR}/*.csr\n"
  },
  {
    "path": "test/prop_mimemail.erl",
    "content": "%% @doc property-based tests for `mimemail' module\n%%\n%% Following limitations of mimemail are discovered and modelled in this suite:\n%% * We may truncate leading and trailing whitespaces \" \" from header values\n%% * We may truncate trailing tabs and whitespaces from payload when Content-Transfer-Encoding is not base64\n%% * For binary payload it's highly recommended to set `#{transfer_encoding => <<\"base64\">>}' explicitly\n-module(prop_mimemail).\n\n-export([\n    prop_plaintext_encode_no_crash/1,\n    prop_multipart_encode_no_crash/1,\n    prop_plaintext_encode_decode_match/1,\n    prop_multipart_encode_decode_match/1,\n    prop_encode_decode_no_mime_version_match/1,\n    prop_quoted_printable/1,\n    prop_smtp_compatible/1\n]).\n\n-include_lib(\"proper/include/proper.hrl\").\n-include_lib(\"stdlib/include/assert.hrl\").\n\nprop_plaintext_encode_no_crash(doc) ->\n    \"Check that any plaintext mail can be encoded without crash\".\n\nprop_plaintext_encode_no_crash() ->\n    ?FORALL(\n        Mail,\n        gen_plaintext_mail(),\n        is_binary(mimemail:encode(Mail))\n    ).\n\nprop_multipart_encode_no_crash(doc) ->\n    \"Check that any multipart mail can be encoded without crash\".\n\nprop_multipart_encode_no_crash() ->\n    ?FORALL(\n        Mail,\n        gen_multipart_mail(),\n        is_binary(mimemail:encode(Mail))\n    ).\n\nprop_plaintext_encode_decode_match(doc) ->\n    \"Check that any plaintext mail can be encoded and decoded without\"\n    \" information loss or corruption\".\n\nprop_plaintext_encode_decode_match() ->\n    ?FORALL(\n        Mail,\n        gen_plaintext_mail(),\n        begin\n            Encoded = mimemail:encode(Mail),\n            Recoded = mimemail:decode(Encoded),\n            ?WHENFAIL(\n                io:format(\n                    \"Orig:~n~p~nEncoded:~n~p~nRecoded:~n~p~n\",\n                    [Mail, Encoded, Recoded]\n                ),\n                match(Mail, Recoded)\n            )\n        end\n    ).\n\nprop_multipart_encode_decode_match(doc) ->\n    \"Check that any plaintext mail can be encoded and decoded without\"\n    \" information loss or corruption\".\n\nprop_multipart_encode_decode_match() ->\n    ?FORALL(\n        Mail,\n        gen_multipart_mail(),\n        begin\n            Encoded = mimemail:encode(Mail),\n            Recoded = mimemail:decode(Encoded),\n            ?WHENFAIL(\n                io:format(\n                    \"Orig:~n~p~nEncoded:~n~p~nRecoded:~n~p~n\",\n                    [Mail, Encoded, Recoded]\n                ),\n                match(Mail, Recoded)\n            )\n        end\n    ).\n\nprop_encode_decode_no_mime_version_match(doc) ->\n    \"Make sure decoder is able to recover from situation when 'mime-version' header is missing\".\n\nprop_encode_decode_no_mime_version_match() ->\n    ?FORALL(\n        Mail,\n        proper_types:oneof([gen_plaintext_mail(), gen_multipart_mail()]),\n        begin\n            Encoded = mimemail:encode(Mail),\n            Recoded = mimemail:decode(\n                strip_mime_version(Encoded),\n                [\n                    {allow_missing_version, true},\n                    {encoding, <<\"utf-8\">>}\n                ]\n            ),\n            ?WHENFAIL(\n                io:format(\n                    \"Orig:~n~p~nEncoded:~n~p~nRecoded:~n~p~n\",\n                    [Mail, Encoded, Recoded]\n                ),\n                match(Mail, Recoded)\n            )\n        end\n    ).\n\nmatch(\n    {TypeA, SubTypeA, HeadersA, ParamsA, BodyA},\n    {TypeB, SubTypeB, HeadersB, ParamsB, BodyB}\n) ->\n    ?assertEqual(TypeA, TypeB),\n    ?assertEqual(SubTypeA, SubTypeB),\n    ?assert(is_map(ParamsA)),\n    ?assert(is_map(ParamsB)),\n    maps:fold(\n        fun\n            (transfer_encoding, _, _) ->\n                %never added during decoding\n                [];\n            (disposition, _, _) when\n                not is_binary(BodyA);\n                BodyA =:= <<>>\n            ->\n                [];\n            (disposition = K, V, _) when is_binary(BodyA) ->\n                %% disposition only applied for non-empty bodies\n                case re:replace(BodyA, \"\\s+\", \"\", [global, {return, binary}]) of\n                    <<>> -> [];\n                    _ -> ?assertEqual(V, maps:get(K, ParamsB))\n                end;\n            (K, KVA, _) when\n                K =:= content_type_params;\n                K =:= disposition_params\n            ->\n                %% assert all Content-Type/Disposition from original mime do present in\n                %% recoded mime; keys should be lowercased\n                KVB = maps:get(K, ParamsB),\n                lists:foreach(\n                    fun({PKA, PVA}) ->\n                        ?assert(lists:member({binstr:to_lower(PKA), PVA}, KVB))\n                    end,\n                    KVA\n                );\n            (K, V, _) ->\n                ?assertEqual(V, maps:get(K, ParamsB))\n        end,\n        [],\n        ParamsA\n    ),\n    %% XXX: we have to strip values of the body and headers, because it seems some types of\n    %% encoding do remove some of whitespaces from payload. Not sure if it's ok...\n    lists:foreach(\n        fun({K, VA}) ->\n            VB = proplists:get_value(K, HeadersB),\n            ?assertEqual(\n                string:trim(VA, both, \" \"),\n                string:trim(VB, both, \" \"),\n                #{\n                    header => K,\n                    b_headers => HeadersB\n                }\n            )\n        end,\n        HeadersA\n    ),\n    case is_binary(BodyA) of\n        true ->\n            ?assertEqual(BodyA, BodyB),\n            true;\n        false ->\n            Bodies = lists:zip(BodyA, BodyB),\n            lists:all(\n                fun({SubBodyA, SubBodyB}) ->\n                    match(SubBodyA, SubBodyB)\n                end,\n                Bodies\n            )\n    end.\n\nprop_quoted_printable(doc) ->\n    \"Make sure quoted-printable encoder works as expected: \"\n    \"* No lines longer than 76 chars \"\n    \"* decode(encode(data)) returns the same result as original input\".\n\nprop_quoted_printable() ->\n    ?FORALL(\n        Body,\n        proper_types:oneof([\n            ?SIZED(Size, printable_ascii(Size * 50)),\n            ?SIZED(Size, printable_ascii_and_cariage(Size * 50)),\n            printable_ascii(),\n            printable_ascii_and_cariage(),\n            nonull_utf8(),\n            proper_types:binary()\n        ]),\n        begin\n            [QPEncoded] = mimemail:encode_quoted_printable(Body),\n            ?assertEqual(Body, mimemail:decode_quoted_printable(QPEncoded)),\n            ?assertNot(has_lines_over(QPEncoded, 76), #{encoded => QPEncoded, orig => Body}),\n            true\n        end\n    ).\n\nprop_smtp_compatible(doc) ->\n    \"Makes sure mimemail never produces output that is not compatible with SMTP, \"\n    \"See https://tools.ietf.org/html/rfc2045 and https://tools.ietf.org/html/rfc2049:\"\n    \"* Should not contain bare '\\r' or '\\n' (ie, $\\r or $\\n in any other form than '\\r\\n' pair). \"\n    \"* Should not contain ASCII codes above 127\"\n    \"* Should not contain 0 byte\"\n    \"* Should not have too long (over 1000 chars) lines\".\n\nprop_smtp_compatible() ->\n    ?FORALL(\n        Mail,\n        proper_types:oneof([gen_multipart_mail(), gen_plaintext_mail()]),\n        begin\n            SevenByte = mimemail:encode(Mail),\n            ?assertNot(has_bare_cr_or_lf(SevenByte), SevenByte),\n            ?assertNot(has_bytes_above_127(SevenByte), SevenByte),\n            ?assertNot(has_zero_byte(SevenByte), SevenByte),\n            ?assertNot(has_lines_over(SevenByte, 1000), SevenByte),\n            true\n        end\n    ).\n\nhas_bare_cr_or_lf(Mime) ->\n    WithoutCRLF = binary:replace(Mime, <<\"\\r\\n\">>, <<\"\">>, [global]),\n    case binary:match(WithoutCRLF, [<<\"\\r\">>, <<\"\\n\">>]) of\n        nomatch -> false;\n        {_, _} -> true\n    end.\n\nhas_bytes_above_127(<<C, _/binary>>) when C > 127 ->\n    true;\nhas_bytes_above_127(<<_, Tail/binary>>) ->\n    has_bytes_above_127(Tail);\nhas_bytes_above_127(<<>>) ->\n    false.\n\nhas_zero_byte(Mime) ->\n    case binary:match(Mime, <<0>>) of\n        nomatch -> false;\n        {match, _} -> true\n    end.\n\nhas_lines_over(Mime, Limit) ->\n    lists:any(\n        fun(Line) ->\n            byte_size(Line) > Limit\n        end,\n        binary:split(Mime, <<\"\\r\\n\">>, [global])\n    ).\n\nstrip_mime_version(MimeBin) ->\n    binary:replace(MimeBin, <<\"MIME-Version: 1.0\\r\\n\">>, <<>>).\n%% re:replace(MimeBin, \"mime-version: 1\\\\.0\\\\s*\", \"\", [caseless, {return, binary}]).\n\n%%\n%% Generators\n%%\n\n%% top-level multipart mimemail()\ngen_multipart_mail() ->\n    {<<\"multipart\">>, proper_types:oneof([<<\"mixed\">>, <<\"alternative\">>]), gen_top_headers(), gen_props(outer),\n        %% Resizing to not create too many sub-bodies, because it's slow\n        ?SIZED(\n            Size,\n            proper_types:resize(\n                max(1, Size div 2),\n                proper_types:list(\n                    proper_types:oneof(\n                        [\n                            gen_embedded_plaintext_mail(),\n                            gen_embedded_html_mail(),\n                            gen_embedded_attachment_mail()\n                        ]\n                    )\n                )\n            )\n        )}.\n\n%% top-level plaintext mimemail()\ngen_plaintext_mail() ->\n    {<<\"text\">>, <<\"plain\">>, gen_top_headers(), gen_props(outer),\n        proper_types:oneof([gen_body(), gen_nonempty_body()])}.\n\n%% Plaintext mimemail(), that is safe to use inside multipart mails\ngen_embedded_plaintext_mail() ->\n    {<<\"text\">>, <<\"plain\">>, gen_headers(), gen_props(embedded), gen_nonempty_body()}.\n\n%% Pseudo-HTML mimemail(), that is safe to use inside multipart mails\ngen_embedded_html_mail() ->\n    {<<\"text\">>, <<\"html\">>, gen_headers(),\n        #{\n            content_type_params => [{<<\"charset\">>, <<\"utf-8\">>}],\n            disposition => <<\"inline\">>\n        },\n        ?LET(\n            Body,\n            gen_body(),\n            <<\"<!doctype html><html><body><p>\", Body/binary, \"</p></body></html>\">>\n        )}.\n\ngen_embedded_attachment_mail() ->\n    {<<\"application\">>, <<\"pdf\">>, gen_headers(), gen_attachment_props(),\n        proper_types:non_empty(proper_types:binary())}.\n\n%% like gen_headers/0, but `From' is always there\ngen_top_headers() ->\n    ?LET(KV, gen_headers(), lists:ukeysort(1, [{<<\"From\">>, <<\"test@example.com\">>} | KV])).\n\n%% [{binary(), binary()}]\ngen_headers() ->\n    AddrHeaders = [<<\"To\">>, <<\"Cc\">>, <<\"Bcc\">>, <<\"Reply-To\">>, <<\"From\">>],\n    ContentHeaders = [\n        <<\"Content-Type\">>, <<\"Content-Disposition\">>, <<\"Content-Transfer-Encoding\">>\n    ],\n    SpecialHeaders = AddrHeaders ++ ContentHeaders,\n    ?LET(\n        KV,\n        proper_types:list(\n            proper_types:frequency(\n                [\n                    {5,\n                        ?SUCHTHAT(\n                            {K, _},\n                            gen_any_header(),\n                            not lists:member(K, SpecialHeaders)\n                        )},\n                    {1, {proper_types:oneof(AddrHeaders), <<\"to@example.com\">>}}\n                ]\n            )\n        ),\n        lists:ukeysort(1, KV)\n    ).\n\n%% This can generate invalid header when it requires some specific format\ngen_any_header() ->\n    {\n        header_name(),\n        proper_types:oneof(\n            [\n                nonull_utf8(),\n                printable_ascii_and_cariage(),\n                printable_ascii()\n            ]\n        )\n    }.\n\n%% #{atom() => any()}\ngen_props(Location) ->\n    Disposition =\n        case Location of\n            outer -> [];\n            embedded -> [{disposition, proper_types:oneof([<<\"inline\">>, <<\"attachment\">>])}]\n        end,\n    ?LET(\n        KV,\n        proper_types:list(\n            proper_types:oneof(\n                Disposition ++\n                    [\n                        {content_type_params, [{<<\"charset\">>, <<\"utf-8\">>}]},\n                        {transfer_encoding, proper_types:oneof([<<\"base64\">>, <<\"quoted-printable\">>])}\n                    ]\n            )\n        ),\n        maps:from_list(KV)\n    ).\n\ngen_attachment_props() ->\n    ?LET(\n        KV,\n        proper_types:list(\n            proper_types:oneof(\n                [\n                    {content_type_params, gen_params()},\n                    {disposition_params, gen_params()}\n                ]\n            )\n        ),\n        maps:from_list([\n            {disposition, <<\"attachment\">>},\n            {transfer_encoding, <<\"base64\">>}\n            | KV\n        ])\n    ).\n\ngen_params() ->\n    proper_types:list(\n        {\n            header_name(),\n            header_name()\n        }\n    ).\n\n%% binary(), guaranteed to be not `<<>>'. Also, try to generate relatively large body\ngen_nonempty_body() ->\n    proper_types:oneof(\n        [\n            proper_types:non_empty(?SIZED(Size, printable_ascii(Size * 30))),\n            proper_types:non_empty(?SIZED(Size, printable_ascii_and_cariage(Size * 30))),\n            proper_types:non_empty(nonull_utf8())\n        ]\n    ).\n\n%% binary()\ngen_body() ->\n    proper_types:oneof(\n        [\n            printable_ascii(),\n            printable_ascii_and_cariage(),\n            nonull_utf8()\n        ]\n    ).\n\n%% `[0-9a-zA-Z_-]*'\nheader_name() ->\n    %% let's limit header names to 20 characters. Too long header names can easily create very long lines\n    ?LET(\n        OrigHdr,\n        proper_types:non_empty(\n            binary_of(\n                \"-_\" ++\n                    lists:seq($0, $9) ++\n                    lists:seq($A, $Z) ++\n                    lists:seq($a, $z)\n            )\n        ),\n        case OrigHdr of\n            <<Max20:20/binary, _/binary>> -> Max20;\n            _ -> OrigHdr\n        end\n    ).\n\nprintable_ascii_and_cariage() ->\n    ?SIZED(Size, printable_ascii_and_cariage(Size)).\n\nprintable_ascii_and_cariage(Size) ->\n    binary_of(\"\\t\\r\\n\" ++ lists:seq(32, 126), Size).\n\nprintable_ascii() ->\n    ?SIZED(Size, printable_ascii(Size)).\n\nprintable_ascii(Size) ->\n    binary_of(lists:seq(32, 126), Size).\n\nbinary_of(Bytes) ->\n    ?SIZED(Size, binary_of(Bytes, Size)).\n\nbinary_of(Bytes, Size) ->\n    ?LET(\n        List,\n        proper_types:resize(Size, proper_types:list(proper_types:oneof(Bytes))),\n        list_to_binary(List)\n    ).\n\n%% any utf-8, except 0\nnonull_utf8() ->\n    ?SUCHTHAT(\n        Chars,\n        proper_unicode:utf8(),\n        case Chars of\n            <<>> ->\n                true;\n            _ ->\n                binary:match(Chars, <<0>>) =:= nomatch\n        end\n    ).\n"
  },
  {
    "path": "test/prop_rfc5322.erl",
    "content": "%% @doc property-based tests for `smtp_util' rfc5322#section-3.4 and RFC-822 parser/serializer\n%% Mainly tests parsing of address-lists and groups:\n%% `login@domain'\n%% `Name <login@domain>'\n%% `Name Surname <login@domain>'\n%% `Name <login1@domain1>, Name2 <login2@domain2>'\n%% `group name:login@domain,Name <login2@domain2>;'\n%% Also different versions of escaping of name / login / domain\n-module(prop_rfc5322).\n\n-export([\n    prop_encode_no_crash/1,\n    prop_encode_scan_no_crash/1,\n    prop_encode_decode_match/1,\n    prop_encode_decode_group/1\n]).\n\n-include_lib(\"proper/include/proper.hrl\").\n-include_lib(\"stdlib/include/assert.hrl\").\n\nprop_encode_no_crash(doc) ->\n    \"Check that any RFC-5322-compliant 'mailbox-list' can be serialized\".\n\nprop_encode_no_crash() ->\n    ?FORALL(\n        AddressList,\n        ?LET(Opts, use_unicode(), gen_address_list(Opts)),\n        is_binary(smtp_util:combine_rfc822_addresses(AddressList))\n    ).\n\nprop_encode_scan_no_crash(doc) ->\n    \"Check that any RFC-5322-compliant 'mailbox-list' can be serialized and then result scanned by lexer\".\n\nprop_encode_scan_no_crash() ->\n    ?FORALL(\n        AddressList,\n        ?LET(Opts, use_unicode(), gen_address_list(Opts)),\n        begin\n            Encoded = smtp_util:combine_rfc822_addresses(AddressList),\n            Res = smtp_rfc5322_scan:string(unicode:characters_to_list(Encoded)),\n            ?WHENFAIL(\n                io:format(\n                    \"AddrList:~n~p~nEncoded:~n~p~nRes:~n~p~n\",\n                    [AddressList, Encoded, Res]\n                ),\n                begin\n                    ?assertMatch({ok, _, 1}, Res),\n                    true\n                end\n            )\n        end\n    ).\n\nprop_encode_decode_match(doc) ->\n    \"Check that any RFC-5322-compliant 'mailbox-list' can be serialized and parsed to the same result\".\n\nprop_encode_decode_match() ->\n    ?FORALL(\n        AddressList,\n        ?LET(Opts, use_unicode(), gen_address_list(Opts)),\n        begin\n            Encoded = smtp_util:combine_rfc822_addresses(AddressList),\n            Res = smtp_util:parse_rfc5322_addresses(Encoded),\n            ?WHENFAIL(\n                io:format(\n                    \"AddrList:~n~p~nEncoded:~n~p~nRes:~n~p~nScan:~n~p~n\",\n                    [\n                        AddressList,\n                        Encoded,\n                        Res,\n                        smtp_rfc5322_scan:string(unicode:characters_to_list(Encoded))\n                    ]\n                ),\n                begin\n                    {ok, Decoded} = Res,\n                    Zip = lists:zip(AddressList, Decoded),\n                    lists:all(fun match/1, Zip)\n                end\n            )\n        end\n    ).\n\nmatch({{OName, OAddr}, {undefined, RAddr}}) when\n    OName == undefined;\n    OName == <<>>;\n    OName == \"\"\n->\n    ?assertEqual(OAddr, unicode:characters_to_binary(RAddr)),\n    true;\nmatch({{OName, OAddr}, {RName, RAddr}}) ->\n    %% smtp_util drops chars below 32 from \"name\" part. Not sure it's correct, but is probably\n    %% not a big deal.\n    ONameNoControl = lists:map(\n        fun\n            (C) when C < 32 -> 32;\n            (C) -> C\n        end,\n        unicode:characters_to_list(OName)\n    ),\n    ?assertEqual(ONameNoControl, RName),\n    ?assertEqual(OAddr, unicode:characters_to_binary(RAddr)),\n    true.\n\nprop_encode_decode_group(doc) ->\n    \"Check that any RFC-5322-compliant 'group' can be serialized and parsed to the same result\".\n\nprop_encode_decode_group() ->\n    ?FORALL(\n        {Name, AddressList},\n        ?LET(Opts, use_unicode(), gen_group(Opts)),\n        begin\n            Encoded = encode_group(Name, AddressList),\n            {ok, Tokens, _} = smtp_rfc5322_scan:string(unicode:characters_to_list(Encoded)),\n            Res = smtp_rfc5322_parse:parse(Tokens),\n            ?WHENFAIL(\n                io:format(\n                    \"Name: '~p'~n\"\n                    \"AddressList: ~p~n\"\n                    \"Encoded: ~p~n\"\n                    \"Res: ~p~n\",\n                    [Name, AddressList, Encoded, Res]\n                ),\n                begin\n                    ?assertMatch({ok, {group, {_, _}}}, Res),\n                    {ok, {group, {ResName, ResList0}}} = Res,\n                    ResList =\n                        lists:map(\n                            fun({AName, {addr, Local, Domain}}) ->\n                                {AName, Local ++ \"@\" ++ Domain}\n                            end,\n                            ResList0\n                        ),\n                    ?assertEqual(unicode:characters_to_list(Name), ResName),\n                    lists:all(fun match/1, lists:zip(AddressList, ResList))\n                end\n            )\n        end\n    ).\n\nencode_group(Name, AddressList) ->\n    EncodedList = smtp_util:combine_rfc822_addresses(AddressList),\n    EncName =\n        case binary:match(Name, <<\"\\\"\">>) of\n            nomatch -> Name;\n            _ -> <<$\\\", (binary:replace(Name, <<\"\\\"\">>, <<\"\\\\\\\"\">>, [global]))/binary, $\\\">>\n        end,\n    <<EncName/binary, \":\", EncodedList/binary, \";\">>.\n\nuse_unicode() ->\n    proper_types:oneof(\n        [#{}, #{}, #{unicode => true}]\n    ).\n\ngen_group(Opts) ->\n    {\n        gen_phrase(Opts),\n        proper_types:oneof(\n            [\n                gen_address_list(Opts),\n                %group might be empty\n                []\n            ]\n        )\n    }.\n\ngen_address_list(Opts) ->\n    proper_types:non_empty(\n        proper_types:list(\n            proper_types:oneof(\n                [\n                    gen_anonymous_name_addr(Opts),\n                    gen_named_name_addr(Opts)\n                ]\n            )\n        )\n    ).\n\ngen_anonymous_name_addr(Opts) ->\n    {\n        proper_types:oneof(\n            [\"\", <<>>, undefined]\n        ),\n        gen_addr_spec(Opts)\n    }.\n\ngen_named_name_addr(Opts) ->\n    {gen_phrase(Opts), gen_addr_spec(Opts)}.\n\n-define(NO_WS_CTL, (lists:seq(1, 8) ++ [11, 12] ++ lists:seq(14, 31) ++ [127])).\n\n%% rfc5322#section-3.4\ngen_addr_spec(Opts) ->\n    ?LET(\n        {Local, Domain},\n        {gen_local_part(Opts), gen_domain(Opts)},\n        <<Local/binary, \"@\", Domain/binary>>\n    ).\n\ngen_local_part(Opts) ->\n    proper_types:oneof(\n        [gen_dot_atom(Opts), gen_quoted_string(Opts)]\n    ).\n\ngen_domain(Opts) ->\n    proper_types:oneof(\n        [gen_dot_atom(Opts), gen_domain_literal(Opts)]\n    ).\n\ngen_domain_literal(Opts) ->\n    DText = maybe_utf8(?NO_WS_CTL ++ lists:seq(33, 90) ++ lists:seq(94, 126), Opts),\n    DContent = proper_types:oneof([<<\"\\\\[\">>, <<\"\\\\]\">> | DText]),\n    ?LET(\n        Str,\n        proper_types:non_empty(proper_types:list(DContent)),\n        <<\"[\", (unicode:characters_to_binary(Str))/binary, \"]\">>\n    ).\n\n%% rfc5322#section-3.2.5\ngen_phrase(Opts) ->\n    Word = proper_types:oneof(\n        [\n            gen_atom(Opts),\n            gen_quoted_string(Opts)\n        ]\n    ),\n    ?LET(\n        Words,\n        proper_types:non_empty(proper_types:list(Word)),\n        unicode:characters_to_binary(lists:join($\\s, Words))\n    ).\n\n%% rfc5322#section-3.2.5\ngen_quoted_string(Opts) ->\n    QText = maybe_utf8(?NO_WS_CTL ++ [33] ++ lists:seq(35, 91) ++ lists:seq(93, 126), Opts),\n    %% QContent = [<<\"\\\\\\\"\">> | QText],\n    QContent = QText,\n    ?LET(\n        Str,\n        proper_types:non_empty(proper_types:list(proper_types:oneof(QContent))),\n        unicode:characters_to_binary([$\\\", Str, $\\\"])\n    ).\n\n%% rfc5322#section-3.2.3\ngen_dot_atom(Opts) ->\n    ?LET(\n        Parts,\n        proper_types:non_empty(proper_types:list(gen_atom(Opts))),\n        unicode:characters_to_binary(lists:join($\\., Parts))\n    ).\n\ngen_atom(Opts) ->\n    Spec = \"!#$%&'*+-/=?^_`{|}~\",\n    Atext = maybe_utf8(lists:seq($0, $9) ++ lists:seq($A, $Z) ++ lists:seq($a, $z) ++ Spec, Opts),\n    ?LET(\n        Str,\n        proper_types:non_empty(proper_types:list(proper_types:oneof(Atext))),\n        unicode:characters_to_binary(Str)\n    ).\n\nmaybe_utf8(Chars, #{unicode := true}) ->\n    %% See `proper_unicode.erl'\n    [\n        proper_types:integer(16#80, 16#7FF),\n        proper_types:integer(16#800, 16#D7FF),\n        proper_types:integer(16#E000, 16#FFFD),\n        proper_types:integer(16#10000, 16#10FFFF),\n        proper_types:oneof(Chars)\n    ];\nmaybe_utf8(Chars, _) ->\n    Chars.\n"
  }
]