Current section
Files
Jump to
Current section
Files
src/gleambox.erl
-module(gleambox).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([get_headers/1, get_header/2, parse_mbox/1, maildir_iterator/1, maildir_iterate/1, parse_mail/1]).
-export_type([m_box/0, mail/0]).
-type m_box() :: {m_box, gleam@dict:dict(binary(), binary()), binary()} |
invalid_m_box.
-type mail() :: {mail,
{ok, binary()} | {error, nil},
{ok, binary()} | {error, nil},
{ok, binary()} | {error, nil},
{ok, binary()} | {error, nil},
{ok, birl:time()} | {error, nil},
{ok, binary()} | {error, nil},
{ok, gleam@dict:dict(binary(), binary())} | {error, nil}} |
invalid_mail.
-spec get_headers(m_box()) -> {ok, gleam@dict:dict(binary(), binary())} |
{error, nil}.
get_headers(Mbox) ->
case Mbox of
invalid_m_box ->
{error, nil};
{m_box, Headers, _} ->
{ok, Headers}
end.
-spec get_header(m_box(), binary()) -> {ok, binary()} | {error, nil}.
get_header(Mbox, Key) ->
case Mbox of
{m_box, Headers, _} ->
_pipe = Headers,
gleam@dict:get(_pipe, Key);
invalid_m_box ->
{error, nil}
end.
-spec parse_body(binary()) -> {ok, binary()} | {error, nil}.
parse_body(Mboxcontents) ->
case gleam@string:split_once(Mboxcontents, <<"\n\n"/utf8>>) of
{ok, Pair} ->
_pipe = gleam@pair:second(Pair),
{ok, _pipe};
{error, _} ->
{error, nil}
end.
-spec get_header_dict(binary()) -> {binary(), binary()}.
get_header_dict(S) ->
_pipe = S,
_pipe@1 = gleam@string:split_once(_pipe, <<": "/utf8>>),
gleam@result:unwrap(_pipe@1, {<<""/utf8>>, <<""/utf8>>}).
-spec remove_dead_space(binary(), binary()) -> binary().
remove_dead_space(Acc, Matched_content) ->
_assert_subject = gleam@regex:from_string(<<"\\s+"/utf8>>),
{ok, Dead_space} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"gleambox"/utf8>>,
function => <<"remove_dead_space"/utf8>>,
line => 98})
end,
_pipe = Dead_space,
_pipe@1 = gleam@regex:split(_pipe, Matched_content),
_pipe@2 = gleam@string:join(_pipe@1, <<" "/utf8>>),
gleam@string:replace(Acc, Matched_content, _pipe@2).
-spec fix_multiline_values(binary()) -> binary().
fix_multiline_values(S) ->
_assert_subject = gleam@regex:compile(
<<": [^\n]+\n\\s+[^\n]+$"/utf8>>,
{options, true, true}
),
{ok, Multi_line_value} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"gleambox"/utf8>>,
function => <<"fix_multiline_values"/utf8>>,
line => 86})
end,
_pipe = Multi_line_value,
_pipe@1 = gleam@regex:scan(_pipe, S),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Match) -> erlang:element(2, Match) end
),
_pipe@3 = gleam@list:scan(_pipe@2, S, fun remove_dead_space/2),
_pipe@4 = gleam@list:first(_pipe@3),
gleam@result:unwrap(_pipe@4, <<"bar"/utf8>>).
-spec parse_headers(binary()) -> {ok, gleam@dict:dict(binary(), binary())} |
{error, nil}.
parse_headers(Mboxcontents) ->
case gleam@string:split_once(Mboxcontents, <<"\n\n"/utf8>>) of
{ok, Pair} ->
_pipe = gleam@pair:first(Pair),
_pipe@1 = fix_multiline_values(_pipe),
_pipe@2 = gleam@string:split(_pipe@1, <<"\n"/utf8>>),
_pipe@3 = gleam@list:map(_pipe@2, fun get_header_dict/1),
_pipe@4 = maps:from_list(_pipe@3),
{ok, _pipe@4};
{error, _} ->
{error, nil}
end.
-spec parse_mbox(binary()) -> m_box().
parse_mbox(Mboxcontents) ->
Headers = parse_headers(Mboxcontents),
Body = parse_body(Mboxcontents),
case {Headers, Body} of
{{ok, Parsed_headers}, {ok, Parsed_body}} ->
{m_box, Parsed_headers, Parsed_body};
{_, _} ->
invalid_m_box
end.
-spec read_file(binary()) -> binary().
read_file(File_path) ->
_pipe = File_path,
_pipe@1 = simplifile:read(_pipe),
gleam@result:unwrap(_pipe@1, <<""/utf8>>).
-spec maildir_iterator(binary()) -> gleam@iterator:iterator(binary()).
maildir_iterator(Mbox_path) ->
_pipe = Mbox_path,
_pipe@1 = simplifile:get_files(_pipe),
_pipe@2 = gleam@result:lazy_unwrap(_pipe@1, fun gleam@list:new/0),
_pipe@3 = gleam@iterator:from_list(_pipe@2),
gleam@iterator:map(_pipe@3, fun read_file/1).
-spec maildir_iterate(binary()) -> gleam@iterator:iterator({binary(), binary()}).
maildir_iterate(Maildir_path) ->
case simplifile:get_files(Maildir_path) of
{ok, Maillist} ->
_pipe = gleam@iterator:from_list(Maillist),
gleam@iterator:map(_pipe, fun(Path) -> {Path, read_file(Path)} end);
{error, _} ->
_pipe@1 = {<<""/utf8>>, <<""/utf8>>},
_pipe@2 = gleam@list:wrap(_pipe@1),
gleam@iterator:from_list(_pipe@2)
end.
-spec mbox_to_mail(m_box()) -> mail().
mbox_to_mail(Mbox) ->
case Mbox of
invalid_m_box ->
invalid_mail;
{m_box, Headers, Body} ->
{mail,
gleam@dict:get(Headers, <<"From"/utf8>>),
gleam@dict:get(Headers, <<"To"/utf8>>),
gleam@dict:get(Headers, <<"Subject"/utf8>>),
gleam@dict:get(Headers, <<"Message-ID"/utf8>>),
case gleam@dict:get(Headers, <<"Date"/utf8>>) of
{ok, Date_str} ->
birl:parse(Date_str);
{error, _} ->
{error, nil}
end,
{ok, Body},
begin
_pipe = Mbox,
get_headers(_pipe)
end}
end.
-spec parse_mail(binary()) -> mail().
parse_mail(Mboxcontents) ->
case parse_mbox(Mboxcontents) of
invalid_m_box ->
invalid_mail;
{m_box, Headers, Body} ->
mbox_to_mail({m_box, Headers, Body})
end.