gen-smtp / gen_smtp

The extensible Erlang SMTP client and server library.
Other
683 stars 266 forks source link

Mimemail proper #247

Closed seriyps closed 3 years ago

seriyps commented 3 years ago

There are 2 commits: 1st one just fixes #246 (I have choosen, unlike Python, to do QP-encoding of \r and \n, because otherwise mimemail is not able to decode the result).

2nd commit is some "proper" property-based test suite for mimemail.

Fix for #246 and test suite were created together, but I decided t split to 2 commits, because they are technically unrelated.

It might be interesting to think about having some "proper" test suite where we compare encoding/decoding of mimemail with some other mime codec (eg, some PHP or Python one) to see if they can inter-communicate (mail encoded by Erlang can be read by Python and vice versa), but next time.

seriyps commented 3 years ago

Is anyone available to review this? @arjan @mworrell ? prop_mimemail suite mainly just generates arbitrary mimemail:mimetuple() structures (plain as well as multipart) and

1) Just tries to encode them with mimemail:encode 2) Tries to encode and then decode them with mimemail and checks that the result of encode+decode sequence is more or less the same as the original mimetuple()

We can later introduce additional checks. Say, validate that for any mimetuple(), when encoded, none of the lines in resulting mime text is longer than 80 chars. Or that resulting mime text only contains 7-bit ASCII etc.

> proper_gen:pick(prop_mimemail:gen_plaintext_mail()).  
{ok,{<<"text">>,<<"plain">>,
     [{<<"6tjAzEe">>,<<"Y<ul\\H">>},
      {<<"7ZV">>,
       <<240,144,128,133,240,144,128,129,225,172,153,88,224,189,
         134,107>>},
      {<<"B-">>,<<207,190,2,90>>},
      {<<"From">>,<<"test@example.com">>},
      {<<"GXz5l1KW">>,<<218,138,111,47,54>>},
      {<<"V6">>,
       <<199,131,208,142,240,144,128,132,235,146,171,240,144,
         128,129,117,...>>},
      {<<"aC_Iw">>,<<"Bi%\\P2\n">>},
      {<<"to-t1M9R0">>,<<>>},
      {<<"tq_x4Kn">>,<<"W<h8 fJ|">>}],
     #{content_type_params => [{<<"charset">>,<<"utf-8">>}],
       disposition => <<"attachment">>,
       transfer_encoding => <<"quoted-printable">>},
     <<"pi@'">>}}
4> proper_gen:pick(prop_mimemail:gen_plaintext_mail()).
{ok,{<<"text">>,<<"plain">>,
     [{<<"1N">>,
       <<219,165,46,240,144,128,129,240,144,128,136,216,130,240,
         144,129,128,42>>},
      {<<"From">>,<<"test@example.com">>},
      {<<"PKbaID">>,<<"j%)\"I">>}, 
      {<<"To">>,<<"to@example.com">>},
      {<<"c">>,<<"M'VW : O)">>},
      {<<"fsHoM7-">>,<<>>},
      {<<"mh9dpzII">>,<<"{">>}],
     #{disposition => <<"attachment">>,
       transfer_encoding => <<"base64">>},
     <<227,150,145,103,240,144,128,142,214,163,206,156,239,
       162,171,231,153,171,238,150,149,16,...>>}}
5> proper_gen:pick(prop_mimemail:gen_multipart_mail()).
{ok,{<<"multipart">>,<<"alternative">>,
     [{<<"Cc">>,<<"to@example.com">>},
      {<<"From">>,<<"test@example.com">>},
      {<<"gG">>,<<100,240,144,128,139,45,240,144,128,130>>},
      {<<"oG">>,<<"vf">>}],
     #{},
     [{<<"text">>,<<"html">>,
       [{<<"03">>,
         <<214,156,219,168,240,144,128,133,239,150,159,240,144,
           128,135,...>>},
        {<<"0XF">>,<<>>},
        {<<"DoTxLp4v62">>,<<"Zi|2">>},
        {<<"LM1V0-zO">>,<<>>},
        {<<"Reply-To">>,<<"to@example.com">>},
        {<<"nII4hN">>,<<"}">>}],
       #{content_type_params => [{<<"charset">>,<<"utf-8">>}],
         disposition => <<"inline">>},
       <<"<!doctype html><html><body><p>GX Kp},pU+</p></body></html>">>},
      {<<"text">>,<<"plain">>,
       [{<<"0LXHtM2et">>,<<">m[hLT">>},
        {<<"84g1xX-qR">>,<<>>},
        {<<"Fx">>,<<"ED\t2:FNX">>},
        {<<"MY0YFh_">>,
         <<240,144,128,137,201,151,240,144,128,151,74>>},
        {<<"ymWky">>,<<70,53,240,144,128,130,240,144,128,139,...>>}],
       #{content_type_params => [{<<"charset">>,<<"utf-8">>}],
         disposition => <<"attachment">>,
         transfer_encoding => <<"base64">>},
       <<"b}OTtcK05">>},
      {<<"text">>,<<"plain">>,[],
       #{content_type_params => [{<<"charset">>,<<"utf-8">>}],
         disposition => <<"inline">>,
         transfer_encoding => <<"base64">>},
       <<240,144,128,132,204,139,3,240,144,128,128,239,130,176>>},
      {<<"text">>,<<"html">>,[],
       #{content_type_params => [{<<"charset">>,<<"utf-8">>}],
         disposition => <<"inline">>},
       <<"<!doctype html><html><body><p></p></body></html>">>}]}}
seriyps commented 3 years ago

Hey, may I do smth more to get the feedback / review?

seriyps commented 3 years ago

Thank you @mworrell !