-module(smtp). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([send/3]). -export_type([error/0]). -type error() :: {tcp_error, mug:error()} | missing_server_code_error | {invalid_server_code_error, binary(), integer()}. -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 15). -spec check_server_code(integer(), bitstring()) -> {ok, nil} | {error, error()}. check_server_code(Expected_code, Response) -> _assert_subject = gleam@bit_array:to_string(Response), {ok, Response_str} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"smtp"/utf8>>, function => <<"check_server_code"/utf8>>, line => 16}) end, gleam@result:'try'( begin _pipe = gleam@string:split_once(Response_str, <<" "/utf8>>), gleam@result:map_error( _pipe, fun(_) -> missing_server_code_error end ) end, fun(_use0) -> {Server_code, _} = _use0, gleam@result:'try'( begin _pipe@1 = gleam_stdlib:parse_int(Server_code), gleam@result:map_error( _pipe@1, fun(_) -> {invalid_server_code_error, Server_code, Expected_code} end ) end, fun(Parsed_code) -> case Parsed_code =:= Expected_code of true -> {ok, nil}; false -> {error, {invalid_server_code_error, Server_code, Expected_code}} end end ) end ). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 48). -spec tcp_send(mug:socket(), binary()) -> {ok, nil} | {error, error()}. tcp_send(Socket, Message) -> _pipe = mug:send(Socket, <>), gleam@result:map_error(_pipe, fun(Field@0) -> {tcp_error, Field@0} end). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 53). -spec tcp_receive(mug:socket(), integer()) -> {ok, bitstring()} | {error, error()}. tcp_receive(Socket, Timeout) -> gleam@result:'try'( begin _pipe = mug:'receive'(Socket, Timeout), gleam@result:map_error( _pipe, fun(Field@0) -> {tcp_error, Field@0} end ) end, fun(Packet) -> _assert_subject = gleam@bit_array:to_string(Packet), {ok, Packet_str} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"smtp"/utf8>>, function => <<"tcp_receive"/utf8>>, line => 59}) end, logging:log(debug, <<"SERVER: "/utf8, Packet_str/binary>>), {ok, Packet} end ). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 36). -spec cmd(mug:socket(), integer(), binary()) -> {ok, bitstring()} | {error, error()}. cmd(Socket, Expected_code, Message) -> logging:log( debug, <<<<"CLIENT: "/utf8, Message/binary>>/binary, "\r\n"/utf8>> ), gleam@result:'try'( tcp_send(Socket, <>), fun(_) -> gleam@result:'try'( tcp_receive(Socket, 500), fun(Packet) -> gleam@result:'try'( check_server_code(Expected_code, Packet), fun(_) -> {ok, Packet} end ) end ) end ). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 65). -spec tcp_connect(binary(), integer(), integer()) -> {ok, mug:socket()} | {error, error()}. tcp_connect(Host, Port, Timeout) -> _pipe = mug:new(Host, Port), _pipe@1 = mug:timeout(_pipe, Timeout), _pipe@2 = mug:connect(_pipe@1), gleam@result:map_error(_pipe@2, fun(Field@0) -> {tcp_error, Field@0} end). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 72). -spec log_sending_info(binary(), integer(), builder:message()) -> nil. log_sending_info(Host, Port, Message) -> logging:log(info, <<"SENDING MAIL"/utf8>>), logging:log( info, <<<<<<"HOST: "/utf8, Host/binary>>/binary, ":"/utf8>>/binary, (begin _pipe = Port, erlang:integer_to_binary(_pipe) end)/binary>> ), logging:log(info, <<"FROM: "/utf8, (erlang:element(2, Message))/binary>>), logging:log( info, <<"TO: "/utf8, (gleam@string:join(erlang:element(3, Message), <<", "/utf8>>))/binary>> ), logging:log(info, <<"SUBJECT: "/utf8, (erlang:element(4, Message))/binary>>), logging:log(info, <<"BODY: "/utf8, (erlang:element(5, Message))/binary>>). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 81). -spec setup_data(builder:message()) -> binary(). setup_data(Message) -> _pipe = <<""/utf8>>, _pipe@1 = gleam@string:append( _pipe, <<<<"Subject: "/utf8, (erlang:element(4, Message))/binary>>/binary, "\r\n"/utf8>> ), _pipe@2 = gleam@string:append( _pipe@1, <<<<"From: <"/utf8, (erlang:element(2, Message))/binary>>/binary, ">\r\n"/utf8>> ), _pipe@3 = gleam@string:append( _pipe@2, <<<<"To: <"/utf8, (gleam@string:join(erlang:element(3, Message), <<","/utf8>>))/binary>>/binary, ">\r\n"/utf8>> ), _pipe@4 = gleam@string:append(_pipe@3, <<"\r\n"/utf8>>), _pipe@5 = gleam@string:append(_pipe@4, erlang:element(5, Message)), gleam@string:append(_pipe@5, <<"\r\n."/utf8>>). -file("/home/andre/Code/gleam/gsmtp/src/smtp.gleam", 91). -spec send(binary(), integer(), builder:message()) -> {ok, nil} | {error, error()}. send(Host, Port, Message) -> log_sending_info(Host, Port, Message), Timeout = 500, gleam@result:'try'( tcp_connect(Host, Port, Timeout), fun(Socket) -> gleam@result:'try'( tcp_receive(Socket, Timeout), fun(_) -> gleam@result:'try'( cmd(Socket, 250, <<"HELO localhost"/utf8>>), fun(_) -> gleam@result:'try'( cmd( Socket, 250, <<<<"MAIL FROM:<"/utf8, (erlang:element(2, Message))/binary>>/binary, ">"/utf8>> ), fun(_) -> gleam@result:'try'( cmd( Socket, 250, <<<<"RCPT TO:<"/utf8, (gleam@string:join( erlang:element( 3, Message ), <<","/utf8>> ))/binary>>/binary, ">"/utf8>> ), fun(_) -> gleam@result:'try'( cmd( Socket, 354, <<"DATA"/utf8>> ), fun(_) -> gleam@result:'try'( cmd( Socket, 250, setup_data(Message) ), fun(_) -> gleam@result:'try'( cmd( Socket, 221, <<"QUIT"/utf8>> ), fun(_) -> {ok, nil} end ) end ) end ) end ) end ) end ) end ) end ).