Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparently try both ipv6 and ipv4 in gen_smtp_client #213

Open
seriyps opened this issue Jun 3, 2020 · 1 comment
Open

Transparently try both ipv6 and ipv4 in gen_smtp_client #213

seriyps opened this issue Jun 3, 2020 · 1 comment

Comments

@seriyps
Copy link
Collaborator

seriyps commented Jun 3, 2020

Why?

Well, shortage of ipv4 addresses. More flexibility. But at the same time, not all mail receivers support ipv6, so, you can't just be ipv6-only

Problem

gen_smtp_client uses gen_tcp:connect/3 and this one always uses ipv4:

> f(), {ok, S} = gen_tcp:connect("google.com", 443, []), inet:peername(S).           
{ok,{{216,58,207,46},443}}

It's possible to tell gen_tcp which protocol to use by providing inet or inet6 options, but if you'll provide both, only 1st one will be used:

1> f(), {ok, S} = gen_tcp:connect("ipv6.google.com", 443, [inet6, inet]), inet:peername(S). 
{ok,{{10752,5200,16385,2057,0,0,0,8206},443}}
2> f(), {ok, S} = gen_tcp:connect("ipv6.google.com", 443, [inet, inet6]), inet:peername(S).
** exception error: no match of right hand side value {error,nxdomain}

Also, smtp_util:mxlookup explicitly resolves A dns if no MX is found and ignores AAAA ones.

lists:map(fun(X) -> {10, inet_parse:ntoa(X)} end, inet_res:lookup(Domain, in, a));

Proposed solutions

So it seems like OTP does not provide an easy way to do this. What we can do instead is to:
A: manually resolve MX - A/AAAA records and try them one-by-one.
B: call gen_tcp:connect("example.com", 25, [inet6]) and if that fails gen_tcp:connect("example.com", 25, [inet]).
Both are quite intrusive changes I would say (can increase latency), so, probably should be turned on by some option? Say {ip_versions, [inet:address_family()]} - this way one can define both priority (elements in a list are tried one-by-one) and can enable/disable ip families by not including to a list.
Also, smth should be done with smtp_util:mxlookup. Either we always return all IPs from MX and A or we just return unresolved domain from mxlookup fallback.

@seriyps seriyps changed the title Transparently try to both ipv6 and ipv4 in gen_smtp_client Transparently try both ipv6 and ipv4 in gen_smtp_client Jun 3, 2020
@seriyps
Copy link
Collaborator Author

seriyps commented Jul 8, 2021

TIL: there is a recommended way of doing this: https://en.m.wikipedia.org/wiki/Happy_Eyeballs

UPD: even more concrete RFC specifically for dual-stack SMTP servers and clients: https://datatracker.ietf.org/doc/html/rfc3974

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant