Skip to content

Instantly share code, notes, and snippets.

@221V
Forked from seriyps/email.erl
Created May 9, 2021 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 221V/902dd0a4dee703188e02b6da17650428 to your computer and use it in GitHub Desktop.
Save 221V/902dd0a4dee703188e02b6da17650428 to your computer and use it in GitHub Desktop.
Send emails using Erlang gen_smtp shortcut.
% Send plaintext email using gen_smtp https://github.com/Vagabond/gen_smtp
% This function sends email directly to receiver's SMTP server and don't use MTA relays.
%
% Example plaintext email:
% Mail = mail_plain(<<"Bob <sender@example.com>">>, <<"Alice <receiver@example.com>">>, <<"The mail subject">>, <<"The mail body">>),
% send_email(Mail).
%
% Example email with image attachment:
% ImgName = "image.jpg",
% {ok, ImgBin} = file:read_file(ImgName),
% Mail = mail_with_attachments(<<"sender@example.com">>, <<"receiver@example.com">>, <<"Photos">>,
% <<"See photo in attachment">>,
% [{ImgName, "image/jpeg", ImgBin}]),
% send_email(Mail).
-spec send_email(email()) -> binary() | {error, atom(), any()} | {error, any()}.
send_email(Email) ->
{From, [To], _Body} = Email,
[_, FromDomain] = split_addr(From),
[_, ToDomain] = split_addr(To),
Options = [{relay, binary_to_list(ToDomain)},
{tls, if_availablex},
{hostname, FromDomain}],
gen_smtp_client:send_blocking(Email, Options).
-spec mail_plain(binary(), binary(), binary(), binary(), Opts) -> email() when
Opts :: [{headers, [{binary(), binary()}]}].
mail_plain(From, To, Subject, Body, Opts) ->
AddHeaders = proplists:get_value(headers, Opts, []),
Mimemail =
{<<"text">>, <<"plain">>,
[
{<<"From">>, From},
{<<"To">>, To},
{<<"Subject">>, Subject},
{<<"Content-Type">>, <<"text/plain; charset=utf-8">>}
| AddHeaders],
[{<<"transfer-encoding">>, <<"base64">>}],
Body},
FromAddr = extract_addr_rfc822(From),
{FromAddr, [extract_addr_rfc822(To)], mimemail:encode(Mimemail)}.
-spec mail_with_attachments(
binary(), binary(), binary(), binary(),
[{Name :: binary(), MimeType :: binary(), Body :: binary()}]) -> email().
mail_with_attachments(From, To, Subject, Body, Attachments) ->
MimeBody = {<<"text">>, <<"plain">>,
[{<<"Content-Type">>, <<"text/plain;charset=utf-8">>},
{<<"Content-Transfer-Encoding">>, <<"quoted-printable">>},
{<<"Content-Disposition">>, <<"inline">>}],
[],
Body},
MimeAttachments = [begin
[Ct1, Ct2] = binary:split(MimeType, <<"/">>),
{Ct1, Ct2,
[{<<"Content-Transfer-Encoding">>, <<"base64">>}],
[{<<"disposition">>, <<"attachment">>},
{<<"disposition-params">>,
[{<<"filename">>, Name}]}],
AtBody}
end
|| {Name, MimeType, AtBody} <- Attachments],
Mimemail = {<<"multipart">>,
<<"mixed">>,
[{<<"From">>, From},
{<<"To">>, To},
{<<"Subject">>, Subject}],
[],
[MimeBody | MimeAttachments]},
FromAddr = extract_addr_rfc822(From),
{FromAddr, [extract_addr_rfc822(To)], mimemail:encode(Mimemail)}.
extract_addr_rfc822(Rfc822) ->
{ok, [{_, Addr}]} = smtp_util:parse_rfc822_addresses(Rfc822),
list_to_binary(Addr).
split_addr(MailAddr) ->
binary:split(MailAddr, <<"@">>).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment