Erlang 用のメール クライアント アダプターを開発しています。fetch コマンドを実行しようとすると問題が発生します。Erlang は本体のコンテンツを取得できません。
これは、netcat を介してコマンドを利用しようとしたときの端末からの出力です。
4 FETCH 2 BODY[2]
* 2 FETCH (BODY[2] {1135}
<div>
test content
</div>
)
4 OK FETCH completed.
gen_tcp サーバーが受信できる唯一の出力は、次のバイナリです。
<<"* 2 FETCH (BODY[2] {1135}\r\n">>
ソースコードは次のとおりです。
-module(mailconnector).
-behaviour(gen_server).
-export([start_link/2, stop/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
start_link(Host, imap) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [Host, 143], []).
stop() ->
gen_server:call(?MODULE, stop).
init([Host, Port]) ->
{ok, Sock} = gen_tcp:connect(Host, Port, [binary, {packet, 0}, {active, true}]),
{ok, {Sock, 0}}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call({login, Username, Password}, _From, State) ->
{NewState, Output} = action(State, string:join(["LOGIN", Username, Password], " ")),
case Output of
{ok, Response, Data} -> Result = {Response, Data};
_ -> Result = false
end,
{reply, Result, NewState};
handle_call(list, _From, State) ->
{NewState, Resp} = action(State, "LIST \"\" \"*\""),
{reply, Resp, NewState};
handle_call({select, MailBox}, _From, State) ->
{NewState, Output} = action(State, string:join(["SELECT", MailBox], " ")),
case Output of
{ok, Response, Data} -> Result = {Response, Data};
_ -> Result = false
end,
{reply, Result, NewState};
handle_call({fetch, Num}, _From, State) ->
{NewState, Output} = action(State, string:join(["FETCH", Num, "BODY[1]"], " ")),
case Output of
{ok, Response, Data} -> Result = {Response, Data};
_ -> Result = false
end,
{reply, Result, NewState};
handle_call(_Command, _From, _State) ->
{reply, not_valid, _State}.
handle_cast(_Command, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
action(_State = {Socket, Counter}, Command) ->
NewCount = Counter+1,
CounterAsList = lists:flatten(io_lib:format("~p ", [NewCount])),
Message = list_to_binary(lists:concat([CounterAsList, Command, "\r\n"])),
io:format("~p~n", [Message]),
gen_tcp:send(Socket, Message),
{{Socket, NewCount}, listener(Socket, NewCount)}.
listener(_Sock, Count) ->
receive
{_, _, Reply} ->
io:format("RECEIVED: ~p~n", [Reply]),
Messages = string:tokens(binary_to_list(Reply), "\r\n"),
io:format("~p~n", [Messages]),
find_message(Messages, Count)
after 5000 ->
timeout
end.
process_message(Message, Count) ->
StringCount = lists:flatten(io_lib:format("~p", [Count])),
case [MCount|PureMessage] = string:tokens(Message, " ") of
_M when StringCount == MCount ->
{ok, string:join(PureMessage, " ")};
_ -> [_Command|Output] = PureMessage, {data, string:join(Output, " ")}
end.
find_message(Messages, Count) ->
find_message(Messages, Count, []).
find_message([], _, _) ->
false;
find_message([H|T], Count, Data) ->
case process_message(H, Count) of
{ok, Message} -> {ok, Message, lists:reverse(Data)};
{data, Output} -> find_message(T, Count, [Output|Data])
end.
どうもありがとうございました。