Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-raise original error in mimemail:decode_header/2 #263

Merged

Conversation

maltoe
Copy link
Contributor

@maltoe maltoe commented Jun 6, 2021

Hello 👋

I had an interesting debugging session today due an odd inexplicable error within mimemail:decode/3:

** (UndefinedFunctionError) function :mimemail.decode_header/2 is undefined or private
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:198: :mimemail.decode_header/2
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:183: :mimemail.decode_headers/3
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:130: :mimemail.decode/3

After this change

** (UndefinedFunctionError) function :iconv.convert/3 is undefined (module :iconv is not available)
    :iconv.convert("UTF-8", "utf-8//IGNORE", "Confirm your email address")
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:282: :mimemail.convert/3
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:249: :mimemail.decode_header_tokens_strict/2
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:188: :mimemail.decode_header/2
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:183: :mimemail.decode_headers/3
    (gen_smtp 1.1.1) testproject/deps/gen_smtp/src/mimemail.erl:130: :mimemail.decode/3

Or is there any reason not to do this? As far as I can tell Type:Reason:Stacktrace is support since OTP 21, so in earlier versions this catch clause wouldn't match, but I guess the error would still be better than the stacktrace-less rethrow? 🤔 Maybe I'm overlooking something.

Thanks for making this library though!

malte

@mworrell
Copy link
Collaborator

mworrell commented Jun 6, 2021

@seriyps @arjan To use this we need to drop support for OTP20, as OTP24 is out we might consider dropping 20 support?

@mworrell
Copy link
Collaborator

mworrell commented Jun 6, 2021

@maltoe thanks, please note that edoc uses html-ish notation and not markdown, I think that is the reason why the test on the docs is failing.

@maltoe maltoe force-pushed the re-raise-original-error-in-mimemail branch from 16d0f47 to f2c0c96 Compare June 6, 2021 10:24
@maltoe
Copy link
Contributor Author

maltoe commented Jun 6, 2021

@mworrell Sorry, you're right it doesn't even compile on OTP20, should have checked that before. This would make it compatible to OTP<=20, but not sure if you would want that?

diff --git a/src/mimemail.erl b/src/mimemail.erl
index 0c5559d..aae3536 100644
--- a/src/mimemail.erl
+++ b/src/mimemail.erl
@@ -80,6 +80,13 @@
                {default_mime_version, ?DEFAULT_MIME_VERSION} % default mime version
        ]).

+% Both the :Stacktrace syntax for catch and the ?OTP_RELEASE macro were introduced in OTP21.
+-ifdef(OTP_RELEASE).
+-define(EXC_WITH_STACK(Type, Reason, Stacktrace), Type:Reason:Stacktrace ->).
+-else.
+-define(EXC_WITH_STACK(Type, Reason, Stacktrace), Type:Reason -> Stacktrace = erlang:get_stacktrace(),).
+-endif.
+
 -type mime_type() :: binary().                  % `<<"text">>'
 -type mime_subtype() :: binary().               % `<<"plain">>'
 -type headers() :: [{binary(), binary()}].      % `[{<<"Content-Type">>, <<"text/plain">>}]'
@@ -190,12 +197,12 @@ decode_header(Value, Charset) ->
        RTokens = tokenize_header(Value, []),
        Tokens = lists:reverse(RTokens),
        Decoded = try decode_header_tokens_strict(Tokens, Charset)
-               catch Type:Reason:Stacktrace ->
+               catch ?EXC_WITH_STACK(T, R, S)
                        case decode_header_tokens_permissive(Tokens, Charset, []) of
                                {ok, Dec} -> Dec;
                                error ->
                                        % re-throw original error
-                                       erlang:raise(Type, Reason, Stacktrace)
+                                       erlang:raise(T, R, S)
                        end
                end,
        iolist_to_binary(Decoded).

Unfortunately on newer OTP releases this produces a deprecation warning:

===> Compiling gen_smtp
../../../../usr/local/lib/erlang/lib/parsetools-2.1.6/include/yeccpre.hrl:60:26: Warning: erlang:get_stacktrace/0 is removed; use the new try/catch syntax for retrieving the stack backtrace

@maltoe
Copy link
Contributor Author

maltoe commented Jul 11, 2021

@mworrell Any news? Would you like me to implement the backwards compatible version as outlined above?

@mworrell
Copy link
Collaborator

@seriyps what do you think? I think that for the 1.0 branch it should be ok to only support 22, 23, and 24. As does rebar3.

That would make hacks for the stack trace unneeded.

/cc @arjan

@mworrell
Copy link
Collaborator

We can merge this after we changed #273 to drop support for OTP20.

@mworrell
Copy link
Collaborator

@maltoe Thanks!

@mworrell mworrell merged commit ae6693a into gen-smtp:master Oct 13, 2021
@maltoe maltoe deleted the re-raise-original-error-in-mimemail branch October 13, 2021 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants