Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

gen_smtp_client: Add support for fallback to HELO.

  • Loading branch information...
commit 0b709ce5107af5cbf6c335175d33a28bda034572 1 parent 0cb4aca
@arjan arjan authored
Showing with 50 additions and 5 deletions.
  1. +50 −5 src/gen_smtp_client.erl
View
55 src/gen_smtp_client.erl
@@ -394,11 +394,31 @@ do_AUTH_each(Socket, Username, Password, [_Type | Tail]) ->
-spec try_EHLO(Socket :: socket:socket(), Options :: list()) -> {ok, list()}.
try_EHLO(Socket, Options) ->
- socket:send(Socket, ["EHLO ", proplists:get_value(hostname, Options, smtp_util:guess_FQDN()), "\r\n"]),
- %% TODO handle fallback to HELO!
- {ok, Reply} = read_possible_multiline_reply(Socket),
- Extensions = parse_extensions(Reply),
- {ok, Extensions}.
+ ok = socket:send(Socket, ["EHLO ", proplists:get_value(hostname, Options, smtp_util:guess_FQDN()), "\r\n"]),
+ case read_possible_multiline_reply(Socket) of
+ {ok, <<"500", _Rest/binary>>} ->
+ % Unrecognized command, fall back to HELO
+ try_HELO(Socket, Options);
+ {ok, <<"4", _Rest/binary>> = Msg} ->
+ quit(Socket),
+ throw({temporary_failure, Msg});
+ {ok, Reply} ->
+ {ok, parse_extensions(Reply)}
+ end.
+
+-spec try_HELO(Socket :: socket:socket(), Options :: list()) -> {ok, list()}.
+try_HELO(Socket, Options) ->
+ ok = socket:send(Socket, ["HELO ", proplists:get_value(hostname, Options, smtp_util:guess_FQDN()), "\r\n"]),
+ case read_possible_multiline_reply(Socket) of
+ {ok, <<"250", _Rest/binary>>} ->
+ {ok, []};
+ {ok, <<"4", _Rest/binary>> = Msg} ->
+ quit(Socket),
+ throw({temporary_failure, Msg});
+ {ok, Msg} ->
+ quit(Socket),
+ throw({permanent_failure, Msg})
+ end.
% check if we should try to do TLS
-spec try_STARTTLS(Socket :: socket:socket(), Options :: list(), Extensions :: list()) -> {socket:socket(), list()}.
@@ -687,6 +707,31 @@ session_start_test_() ->
}
end,
fun({ListenSock}) ->
+ {"retry with HELO when EHLO not accepted",
+ fun() ->
+ Options = [{relay, "localhost"}, {port, 9876}, {hostname, "testing"}],
+ {ok, _Pid} = send({"test@foo.com", ["foo@bar.com"], "hello world"}, Options),
+ {ok, X} = socket:accept(ListenSock, 1000),
+ socket:send(X, "220 \r\n"),
+ ?assertMatch({ok, "EHLO testing\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "500 5.3.3 Unrecognized command\r\n"),
+ ?assertMatch({ok, "HELO testing\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "250 Some banner\r\n"),
+ ?assertMatch({ok, "MAIL FROM: <test@foo.com>\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "250 ok\r\n"),
+ ?assertMatch({ok, "RCPT TO: <foo@bar.com>\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "250 ok\r\n"),
+ ?assertMatch({ok, "DATA\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "354 ok\r\n"),
+ ?assertMatch({ok, "hello world\r\n"}, socket:recv(X, 0, 1000)),
+ ?assertMatch({ok, ".\r\n"}, socket:recv(X, 0, 1000)),
+ socket:send(X, "250 ok\r\n"),
+ ?assertMatch({ok, "QUIT\r\n"}, socket:recv(X, 0, 1000)),
+ ok
+ end
+ }
+ end,
+ fun({ListenSock}) ->
{"a valid complete transaction without TLS advertised should succeed",
fun() ->
Options = [{relay, "localhost"}, {port, 9876}, {hostname, "testing"}],
Please sign in to comment.
Something went wrong with that request. Please try again.